Asp.net core mvc analysis: mvc Execution Process (1), coremvc

Source: Internet
Author: User

Asp.net core mvc analysis: mvc Execution Process (1), coremvc

The preceding describes the routing process. Let's take a look at the MvcRouteHandler code:

Public Task RouteAsync (RouteContext context ){...... // Search for the set of compliant ActionDescriptor var candidates = _ actionSelector Based on the route information. selectCandidates (context); if (candidates = null | candidates. count = 0) {_ logger. noActionsMatched (context. routeData. values); return TaskCache. completedTask;} // select the most compliant ActionDescriptor var actionDescriptor = _ actionSelector according to the constraints. selectBestCandidate (context, candidates); if (actionDescriptor = null) {_ logger. noActionsMatc Hed (context. routeData. values); return TaskCache. completedTask;} context. handler = (c) => {var routeData = c. getRouteData (); var actionContext = new ActionContext (context. httpContext, routeData, actionDescriptor); if (_ actionContextAccessor! = Null) {_ actionContextAccessor. actionContext = actionContext;} var invoker = _ actionInvokerFactory. createInvoker (actionContext); if (invoker = null) {throw new InvalidOperationException (Resources. formatActionInvokerFactory_CouldNotCreateInvoker (actionDescriptor. displayName);} return invoker. invokeAsync () ;}; return TaskCache. completedTask ;}

Before giving a detailed introduction to the search logic of ActionDescriptor, let's take a look at what ActionDescriptor is and how it gets it?

We started tracking from IActionSelector. SelectCandidates and got the following call relationship according to the dependency injection configuration of AddMvcCoreServices provided by MvcCoreServiceCollectionExtensions:

In the defaapplapplicationmodelprovider. OnProvidersExecuting method, class information in the Assembly is parsed through reflection. Let's analyze the controller-Class Analysis Code, which is in the CreateControllerModel method.

Protected virtual ControllerModel CreateControllerModel (TypeInfo typeInfo ){...... // Obtain RouteAttribute information. This is a loop until the first class that defines the IRouteTemplateProvider feature is found. Therefore, if RouteAttribute is not configured for the subclass, IRouteTemplateProvider [] routeAttributes = null; do {routeAttributes = currentTypeInfo. getCustomAttributes (inherit: false ). ofType <IRouteTemplateProvider> (). toArray (); if (routeAttributes. length> 0) {// Found 1 or more route attributes. break;} currentTypeInfo = currentTypeInfo. baseTyp E. GetTypeInfo ();} while (currentTypeInfo! = ObjectTypeInfo );...... Var controllerModel = new ControllerModel (typeInfo, attributes); // create Selectors. This requires AddRange (controllerModel. selectors, CreateSelectors (attributes); // obtain the Controller name controllerModel. controllerName = typeInfo. name. endsWith ("Controller", StringComparison. ordinalIgnoreCase )? TypeInfo. name. substring (0, typeInfo. name. length-"Controller ". length): typeInfo. name; // Add the filter feature to the AddRange (controllerModel. filters, attributes. ofType <IFilterMetadata> (); // obtain the route rule data. The value of foreach (var routeValueProvider in attributes must be equal to the value specified in the request. ofType <IRouteValueProvider> () {controllerModel. routeValues. add (routeValueProvider. routeKey, routeValueProvider. routeValue);} // api-related configuration va R apiVisibility = attributes. OfType <IApiDescriptionVisibilityProvider> (). FirstOrDefault (); if (apiVisibility! = Null) {controllerModel. ApiExplorer. IsVisible =! ApiVisibility. IgnoreApi;} var apiGroupName = attributes. OfType <IApiDescriptionGroupNameProvider> (). FirstOrDefault (); if (apiGroupName! = Null) {controllerModel. apiExplorer. groupName = apiGroupName. groupName;} // whether the analysis controller implements the action filter and result filter interfaces. If we need to implement a special action filter or result filter for a controller, you don't need to create a filter feature class separately, so you can directly implement the interface of the controller. This facilitates if (typeof (IAsyncActionFilter ). getTypeInfo (). isAssignableFrom (typeInfo) | typeof (IActionFilter ). getTypeInfo (). isAssignableFrom (typeInfo) {controllerModel. filters. add (new ControllerActionFilter ();} if (typeof (IAsyncResultFilter ). getTypeInfo (). isAssignableFrom (typeInfo) | typeof (IResultFilter ). getTypeInfo (). isAssignableFrom (typeInfo) {controllerModel. filters. add (new ControllerResultFilter ();} return controllerModel ;}

  

After the above method is completed, a ControllerModel object is obtained. The CreateActionModel method creates an ActionModel object. The analysis process is similar to the CreateControllerModel method, so we will not introduce it again, finally, the following hierarchical relationship objects are obtained:

ApplicationModel-> ControllerModel-> ActionModel

Return to the ActionSelector. SelectCandidates method and call the ActionSelectionDecisionTree. Select method. The Code is as follows:

 public IReadOnlyList<ActionDescriptor> Select(IDictionary<string, object> routeValues)        {            var results = new List<ActionDescriptor>();            Walk(results, routeValues, _root);            return results;        }

_ Root is a type of DecisionTreeNode <ActionDescriptor>, which is a search tree generated by DecisionTreeBuilder <ActionDescriptor>. GenerateTree. The DecisionTreeBuilder class is located in the Route application. By viewing the DecisionBuilder code, we find that an IClassifier is required for GenerateTree. In the mvc Framework, the implementation is ActionDescriptorClassifier. In the GetCriteria method, the corresponding IDictionary <string, DecisionCriterionValue>, this will exist as the branch of the tree when the search tree is generated. For details, see DecisionTreeBuilder <TItem>. generateTree will understand.

The search tree is available, ActionSelector. selectCandidates uses this tree to match the route data of the current request on the tree, and obtains all the actiondescriptors that meet the requirements. Then, it calls SelectBestCandidate to obtain the most qualified ActionDescriptor, if the last searched ActionDescriptor is not one, AmbiguousActionException is thrown.

Continue MvcRouteHandler. After finding the ActionDescriptor, set context. Handler.

Context. handler = (c) => {var routeData = c. getRouteData (); // instantiate the ActionContext object var actionContext = new ActionContext (context. httpContext, routeData, actionDescriptor); if (_ actionContextAccessor! = Null) {_ actionContextAccessor. actionContext = actionContext;} // create IActionInvoker var invoker = _ actionInvokerFactory. createInvoker (actionContext); if (invoker = null) {throw new InvalidOperationException (Resources. formatActionInvokerFactory_CouldNotCreateInvoker (actionDescriptor. displayName);} // execute the invoker to process the request return invoker. invokeAsync ();};

  

First come here, next article, continue to analyze what has been done after invoker.

  

  

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.