Interpreting ASP. NET 5 & MVC6 series (10): Controller and Action, interpreting ASP. NET

Source: Internet
Author: User

Interpreting ASP. NET 5 & MVC6 series (10): Controller and Action, interpreting ASP. NET

We know that in MVC5 and earlier versions, the lifecycles of the two frameworks are different. In the new version of MVC6, the MVC Controller/Web API Controller has already been integrated into one, this chapter describes the definition and use of Controller and Action, and how to query the corresponding Controller and Action based on the routing in the MVC framework.

Definition and use of Controller & Action

In the new version of MVC6 framework, a Controller base class is still provided.Url,RouteData,HttpContext,Request,ResponseIn addition,IServiceProviderTypeResovlerThis is a dependency injection container used to obtain the specified type of instance objects in the current request scope.

It complies with the following rules:

Inherited fromMicrosoft.AspNet.Mvc.ControllerThe class must be a Controller, whether there is a Controller suffix or not. Do not inheritMicrosoft.AspNet.Mvc.ControllerTo use the custom XXXController of as the MVC Controller, you must referenceMicrosoft.AspNet.MvcRelated assembly. If you do not want the Controller class that meets the preceding conditions to act as the Controller, you must addNonControllerAttributeFeatures. Similarly, if you do not want to use a method in a Controller as an Action, you must addNonActionAttributeFeatures.

Note the following features:

Features Description
ActionNameAttribute Define the Action name (which can be different from the Action method name)
AcceptVerbsAttribute Defines the names of supported Http methods. One or more methods are supported.
ActivateAttribute The dependency injection tag can be placed on attributes or fields with the set permission.
ResponseCacheAttribute Set Client Cache for a Controller or Action.
RequireHttpsAttribute The limit must be Https requests.
RemoteAttribute When the request is marked as an Ajax request, the server does not verify the form.
NonControllerAttribute Mark that this class is not a Controller.
NonActionAttribute Mark this method as not an Action.

Search Mechanism of Controller

From the above chapter, we know that MVC6 not only supports the normal Controller (inherited from the sub-class of the Controller base class), but also supports the Controller of POCO, in this section, we will study the Controller's search principle and mechanism.

First, to determine whether a class is a Controller, you must first determine the number of datasets in which such classes are defined.Microsoft.AspNet.MvcIn the namespaceIAssemblyProviderThe interface overwrites all the assemblies that may define the Controller. The default implementation of this interface isDefaultAssemblyProviderClass. In this class, it is necessary to set the condition that the Controller that defines MVC must reference one or more of the following assemblies. The list is as follows:

Microsoft.AspNet.MvcMicrosoft.AspNet.Mvc.CoreMicrosoft.AspNet.Mvc.ModelBindingMicrosoft.AspNet.Mvc.RazorMicrosoft.AspNet.Mvc.Razor.HostMicrosoft.AspNet.Mvc.TagHelpersMicrosoft.AspNet.Mvc.XmlMicrosoft.AspNet.PageExecutionInstrumentation.Interfaces

That is to say, if you define a referenceMicrosoft.AspNet.MvcThe POCO Controller is regarded as the Controller of MVC. In other words, if the POCO Controller class you define does not reference any assembly in the above assembly, these Controller classes will not be considered MVC Controller.

Assembly search

Currently, there are two ways to customize the search mechanism of the Controller. The first is to inheritIAssemblyProviderImplementationCandidateAssembliesMethod (or overloadDefaultAssemblyProvider) To define your own logic. The interface is defined as follows:

public interface IAssemblyProvider{ IEnumerable<Assembly> CandidateAssemblies { get; }}

Another method may be relatively simpler, that is, to useIServicesCollectionTo define the assembly to be searched:

services.AddMvc().WithControllersAsServices(new[]{ typeof(MyController).Assembly, typeof(ExternalPocoController).Assembly});

After using the above Code, the system willDefaultAssemblyProviderSwitchFixedSetAssemblyProviderTo implement the above judgment mechanism, that is, to search in a fixed range of sets.

Assembly screening

After the Assembly is determined, another problem arises. How can we determine whether an assembly references the Assembly listed in the necessary conditions of the above MVC? The answer is,Microsoft.Framework.RuntimeInILibraryManagerInterface instanceGetReferencingLibrariesMethod, you can find how many assemblies reference one of the above lists. For exampleMicrosoft.AspNet.MvcTo find the number of assemblies that reference the Assembly. The example is as follows:

var col = this.Resolver.GetRequiredService<ILibraryManager>();var data = col.GetReferencingLibraries("Microsoft.AspNet.Mvc");

The usage code of this function in the default DefaultAssemblyProvider implementation class is as follows:

protected virtual IEnumerable<ILibraryInformation> GetCandidateLibraries(){ if (ReferenceAssemblies == null) {  return Enumerable.Empty<ILibraryInformation>(); } // GetReferencingLibraries returns the transitive closure of referencing assemblies // for a given assembly. return ReferenceAssemblies.SelectMany(_libraryManager.GetReferencingLibraries)        .Distinct()        .Where(IsCandidateLibrary);}

Controller judgment

After determining the Assembly that meets the necessary conditions, you can traverse all the types in the Assembly and then determine whether the type is Controller. In the Controller judgment of the new versionIControllerTypeProviderInterface, which providesControllerTypesThe read-only attribute is used to obtain all the defined controllers. The interface definition is as follows:

public interface IControllerTypeProvider{ IEnumerable<TypeInfo> ControllerTypes { get; }}

DefaultControllerTypeProviderIs the default implementation of this interface. When querying qualified Controller, this default implementation class definesIsControllerMethod to Determine whether a type is Controller. The specific logic is as follows:

Protected internal virtual bool IsController ([NotNull] TypeInfo typeInfo, [NotNull] ISet <Assembly> candidateAssemblies) {if (! TypeInfo. isClass) // This type must be a class {return false;} if (typeInfo. isAbstract) // This class must not be an abstract class {return false;} // We only consider public top-level classes as controllers. isPublic returns false for nested // classes, regardless of visibility modifiers if (! TypeInfo. isPublic) // This class must be a Public class (and not nested). The nested class cannot be Controller {return false;} if (typeInfo. containsGenericParameters) // This class cannot be a generic class {return false;} if (! TypeInfo. Name. EndsWith (ControllerTypeName, StringComparison. OrdinalIgnoreCase )&&! DerivesFromController (typeInfo, candidateAssemblies) // This class ends with a Controller, or inherits from the Controller base class, or its parent class is also a Controller. {Return false;} if (typeInfo. IsDefined (typeof (NonControllerAttribute) // This class cannot set the NonControllerAttribute attribute {return false;} return true ;}

You can also implement it by yourselfIControllerTypeProviderInterface to define its own Controller judgment logic, but it is fixed with some assembly types, MVC inIServicesCollectionAn extension method is also provided to limit some specific Controller types. The example is as follows:

services.AddMvc().WithControllersAsServices(new[] {  typeof(MyController),  typeof(ExternalPocoController) });

After using the above Code, the system willDefaultControllerTypeProviderSwitchFixedSetControllerTypeProviderTo implement the above judgment mechanism, that is, to limit some specific classes as Controller, other types cannot be as Controller.

Action lookup mechanism

The Action is selected throughIActionSelectorInterface default implementation classDefaultActionSelectorInSelectAsyncSelect the most matched Action through context and route data. The Code is as follows:

public Task<ActionDescriptor> SelectAsync([NotNull] RouteContext context){ // ...}

There is another way to determine whether a method is Action, that isIActionModelBuilderInterface. The default implementation of this interface isDefaultActionModelBuilderClass. The implementation method is as follows:

Public IEnumerable <ActionModel> BuildActionModels ([NotNull] TypeInfo typeInfo, [NotNull] MethodInfo methodInfo) {if (! IsAction (typeInfo, methodInfo) {return Enumerable. Empty <ActionModel> () ;}// ...... omit other code}

This implementation method uses an internalIsActionMethod to Determine whether the method is a real Action method. The Code is as follows:

Protected virtual bool IsAction ([NotNull] TypeInfo typeInfo, [NotNull] MethodInfo methodInfo) {// The SpecialName bit is set to flag members that are treated in a special way by some compilers // (such as property accessors and operator overloading methods ). if (methodInfo. isSpecialName) // it cannot be a special name (such as an overloaded operator or attribute accessor) {return false;} if (methodInfo. isDefined (typeof (NonActionAttribute) // The NonActionAttribute attribute {return false;} // Overriden methods from Object class, e.g. equals (Object), GetHashCode (), etc ., are not valid. if (methodInfo. getBaseDefinition (). declaringType = typeof (object) // it cannot be an overloaded method, such as Equals and GetHashCode {return false ;} // Dispose method implemented from IDisposable is not valid if (IsIDisposableMethod (methodInfo, typeInfo) // it cannot be the Dispose method {return false;} if (methodInfo. isStatic) // it cannot be a static method {return false;} if (methodInfo. isAbstract) // cannot be an abstract method {return false;} if (methodInfo. isConstructor) // cannot be the {return false;} if (methodInfo. isGenericMethod) // cannot be a generic method {return false;} return methodInfo. isPublic; // The Public method must be used}

The above content is important Code related to Controller and Action Search. For detailed principles and steps, seeMicrosoft.AspNet.Mvc.CoreAll source code under the Assembly.

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.