Interpreting ASP 5 & MVC6 Series: Controller and action

Source: Internet
Author: User

Original: Interpretation of ASP. 5 & MVC6 Series: Controller and action

We know that in MVC5 and previous versions, the life cycle of the two frames is not the same, in the new MVC6, the MVC controller/web API Controller has been merged, this chapter we mainly explain the Controller and action definition and use, And in the MVC framework, how to query the corresponding controller and action based on the route.

Definition and use of controller&action

In the new MVC6 framework, a controller base class is still provided, where, in addition to the,,,,, and Url RouteData HttpContent Request Response Other, a IServiceProvider type of Resovler attribute is provided, which is a container of dependency injection. Used to get an instance object of the specified type within the current request scope.

It complies with the following rules:

    1. Inherited Microsoft.AspNet.Mvc.Controller classes are definitely controllers, regardless of the controller suffix.
    2. Custom xxxcontroller that do not inherit Microsoft.AspNet.Mvc.Controller if you want to be an MVC controller, you must refer to Microsoft.AspNet.Mvc the associated assembly.
    3. If you do not want a controller class that satisfies the above conditions as a controller, you need to add attributes to the class NonControllerAttribute .
    4. Similarly, if you do not want a method in a controller to act as an action, you need to add an attribute to the method NonActionAttribute .

There are several other features to note:

features Description
Actionnameattribute Defines the name of the action (which can be different from the action method name)
Acceptverbsattribute Defines the supported HTTP method names, supporting single or multiple method.
Activateattribute A tag that relies on injection, which can be placed on a property or field with set permissions.
Responsecacheattribute Sets the client cache for a controller or action.
Requirehttpsattribute The limit must be an HTTPS request.
Remoteattribute Marked as an AJAX request, the server side does not validate validation of form forms.
Noncontrollerattribute Flag This class is not a controller.
Nonactionattribute Flag This method is not an action.
The lookup mechanism of controller

From the above section, we know that MVC6 not only supports the normal controller (inherited from the Controller base class subclass), but also supports POCO controller, this section we will examine the controller's mechanism of finding principle.

First, to determine whether a class is a controller, you must first decide how many assemblies are defined in such a class. The Microsoft.AspNet.Mvc interface under the namespace IAssemblyProvider is the override to find all the assemblies that might define the controller, the default implementation of which is the class, DefaultAssemblyProvider in which the necessary conditions are set, The controller that defines MVC must refer to one or more assemblies in the following assembly 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, if you define a referenced Microsoft.AspNet.Mvc DLL class library, the Poco controller inside it will be considered an MVC controller. In other words, if you define a Poco controller class that does not reference any of the assemblies in the above assembly, then these controller classes are not considered to be MVC controllers.

Lookup of Assemblies

There are two ways to customize the lookup mechanism of a controller, the first of which is to inherit the IAssemblyProvider implementation CandidateAssemblies method (or overload DefaultAssemblyProvider ) to define your own logic. The interface is defined as follows:

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

Another way, which may be relatively simple, is to use the IServicesCollection extension method defined above to define the assembly to find:

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

Using the above code, the system will DefaultAssemblyProvider switch FixedSetAssemblyProvider to achieve the above judgment mechanism, namely: in the fixed scope of the assembly to find.

Filtering for assemblies

Once the assembly has been identified, the other question is, how do you tell if an assembly refers to the assemblies listed in the MVC prerequisites above? The answer is that Microsoft.Framework.Runtime in the method of the ILibraryManager interface instance GetReferencingLibraries , you can find out how many assemblies refer to one of the assemblies in the preceding list. For example, depending on the assembly, you can Microsoft.AspNet.Mvc find out how many assemblies reference the assembly, as shown in the following example:

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

The use code for this feature in the Defaultassemblyprovider default 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's judgment

Once you have determined which assembly meets the requirements, you can iterate through all the types in the assembly and then determine if the type is a controller. In the new version of Controller judgment, the implementation of this function is an IControllerTypeProvider interface, which provides a ControllerTypes read-only property to obtain all the defined controller, the interface is defined as follows:

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

The

defaultcontrollertypeprovider is the default implementation of this interface, and when you query a qualified controller, the default implementation class defines a Iscontroller method, which is used to determine whether a type is a controller, with the following logic:

protected internal virtual bool Iscontroller ([Notnull] TypeInfo typeinfo, [not    Null] iset<assembly> candidateassemblies) {if (!typeinfo.isclass)//The type must be a class {return false;    } if (typeinfo.isabstract)//The class must not be 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)//The class must be a P    Ublic class (and not nested), the nested class cannot be a controller {return false;    } if (typeinfo.containsgenericparameters)//The class cannot be a generic class {return false; } if (!typeinfo.name.endswith (Controllertypename, stringcomparison.ordinalignorecase) &&!    Derivesfromcontroller (TypeInfo, candidateassemblies))//The 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)))//The class cannot set the Noncontrollerattribute attribute {REturn false; } return true;

You can also implement your own IControllerTypeProvider interface to define your own controller judgment logic, but with fixed certain assembly types, MVC IServicesCollection also provides an extension method for restricting some controller-specific types, as shown in the following example:

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

Using the above code, the system will DefaultControllerTypeProvider switch FixedSetControllerTypeProvider to achieve the above-mentioned judgment mechanism, that is: restricting certain classes as controller, other types can not be used as controller.

Find mechanism for action

The action is chosen by the IActionSelector default implementation class of the interface DefaultActionSelector , and in the implemented SelectAsync method, the best matching action is selected through the context and routing data, with the following schematic code:

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

There is another place to determine whether a method is an action, that is the IActionModelBuilder interface, the default implementation of the interface is a DefaultActionModelBuilder class, the implementation method is as follows:

public IEnumerable<ActionModel> BuildActionModels([NotNull] TypeInfo typeInfo,                                                  [NotNull] MethodInfo methodInfo){    if (!IsAction(typeInfo, methodInfo))    {        return Enumerable.Empty<ActionModel>();    }    // ....省略其它代码}

The implementation method, through an internal IsAction method to determine whether the method is a real action method, the specific code is as follows:

Protected virtual bool Isaction ([Notnull] TypeInfo typeinfo, [notnull] MethodInfo MethodInfo) {//the SpecialName bit I s set to flag members that is treated in a special-some compilers//(such as property accessors and operator O    Verloading methods).    if (methodinfo.isspecialname)//cannot be a special name (such as an overloaded operator or property accessor) {return false;    } if (Methodinfo.isdefined (typeof (Nonactionattribute)))//cannot declare Nonactionattribute attribute {return false;    }//Overriden methods from object class, e.g. Equals (object), GetHashCode (), etc, is not valid. if (Methodinfo.getbasedefinition ().    DeclaringType = = typeof (object)//cannot be an overloaded method, such as Equals and GetHashCode {return false; }//Dispose method implemented from IDisposable are not valid if (Isidisposablemethod (MethodInfo, TypeInfo))//cannot be    Dispose method {return false;    } if (methodinfo.isstatic)//cannot be a static method {return false; } if (Methodinfo.isabstract)//cannot be an abstract method {return FALse    } if (Methodinfo.isconstructor)//cannot be a constructor {return false;    } if (Methodinfo.isgenericmethod)//cannot be a generic method {return false;   } return methodinfo.ispublic; Must be public method}

The above is about controller and action lookup related important code, detailed principle steps, please refer to Microsoft.AspNet.Mvc.Core the assembly of all source code.

Synchronization and recommendations

This article has been synchronized to the Catalog index: Interpreting ASP. & MVC6 Series

Interpreting ASP 5 & MVC6 Series: Controller and action

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.