New Routing Features In ASP.NET 5 and MVC6, the Routing function has been completely rewritten. Although the usage is somewhat similar, the principle of Routing is completely different from the previous one. The Routing framework can not only support MVC and Web API, but also support general ASP.NET 5 programs. The new version has the following changes. First of all, the Routing system is based on ASP.NET 5, which is a routing framework independent of MVC, not based on MVC. MVC just extends a shortcut on it. Secondly, in ASP.NET 5, there is no difference between MVC and Web API controllers, that is, they are combined into one. Both are derived from the same Controller base class. In other words, the Routing framework is applicable to both. If it is applicable to MVC, it also means it is applicable to Web API. ***, you can use inline constraints and parameter options in both convention-based and attribute-based Route declarations. For example, you can agree on the data type of a parameter in the route, mark a parameter as an optional type, or provide it with a default value. The main process of the Routing framework The basic Routing framework is implemented based on Middleware, so that it can be added to the HTTP request Pipeline. It can be used in combination with any other Middleware, such as static file handlers, error pages, or SignalR servers. Before using the Routing framework, you must first understand the role of Routing, which is very simple: For HTTP requests, the Routing system is responsible for finding the matching route, creating route data, and dispatching the request to the handler corresponding to the route. The selection of Controller and Action is just a specific implementation of MVC's Handler, which uses route data and other information in the HTTP request to select the Controller and Action to be executed. In the new version of MVC6, the name of the handler is MvcRouteHandler. The execution flow of the routing system is as follows : ASP.NET 5 listens to an HTTP request. The Routing Middleware then tries to match the request with a route in the route collection. Once a request is successfully matched, the handler corresponding to the route is found. Call the RouteAsync method on the handler (because all handlers must implement this interface method). RoutingContext has an IsHandled flag. If the flag is set to true, it means that the request has been successfully processed by the handler. If it is set to false, it means that the handler cannot process the request and the system will match another route for it. It is a little different from the previous Routing system. Once the old version of the Routing system successfully matches a route, it will hand it over to its corresponding Handler, regardless of whether the corresponding Handler can handle the request. Therefore, the route match is successful, but the corresponding action cannot be found. At this time, a 404 error will occur. The new version has made improvements to the above step 4 (returning control to the Routing system for re-matching), which looks very good. Improvements to Route parameters and constraints In the previous route settings, to constrain the data type of a parameter, we need to use the following code:
In the new version of route, you can directly set Product/{productId:int}, and the constraints follow the following conventions:
The following constraints are currently supported: For optional parameters, the value needs to be followed by a question mark after the constraint type, as shown below:
If the parameter is required and you need to keep a default value, you can set it as follows:
General Routing Regarding the example usage, we will not start with MVC, but with the normal Routing usage. When adding a new version of route, the TemplateRoute instance is added by default, and a Handler must be set when the instance is instantiated. For example, we first create an empty ASP.NET 5 project, and add the assembly "Microsoft.AspNet.Routing": "1.0.0-beta3" in the dependencies node of the project.json file, and add the following code to the Configure method of Startup.cs:
Here, we set the Handler for HTTP request processing to DebuggerRouteHandler, which inherits from IRouter. The example code is as follows:
The above class, after inheriting IRouter, must implement a RouteAsync method and set IsHandled to true if the processing is successful. Visit the following URL to view the corresponding results:
Note: TemplateRoute and DebuggerRouteHandler are both inherited from IRouter, and are the core of achieving the aforementioned avoidance of 404 errors (continue matching the next route). Routing in MVC In the MVC sample program, we only need to configure the MapRoute method in the delegate to define various routes when calling the app.UseMVC method. Here we take a blank project as an example to see how to use the MVC route. ***Step: Reference the assembly "Microsoft.AspNet.Mvc": "6.0.0-beta3" in the dependencies node of the project.json file. Part 2: Add MVC Middleware, use MVC, and then add a default route. The code is as follows:
Step 3: Create the following three controllers respectively, where ProductsController inherits from Controlle under Microsoft.AspNet.Mvc
Visiting http://localhost:5000/products and http://localhost:5000/demo both display normal output results; while visiting http://localhost:5000/api returns json data. This is the integration of MVC and API that we talked about in the previous new features of ASP.NET 5. It also does not need to inherit from the Controller base class (but the class name must end with Controller). The core of this technology is the Controller search mechanism. For how to find the appropriate assembly in a project, please refer to the "Controller and Action" chapter. The new version of MVC has two conditions when determining the Controller: either it inherits from Controller, or it references the MVC assembly and the class name ends with Controller. Therefore, when creating MVC Controller and Web API Controller, if you do not need related contexts (such as HTTPContext, ActionContext, etc.), you do not need to inherit from the Controller base class; but it is recommended to inherit from Controller because you can make more use of the methods and properties of the base class. Regardless of whether you inherit or not, all the Controller classes you define must go through the various life cycles of MVC. Let's verify this through ActionFilter: ***Step: Reference the assembly "Microsoft.AspNet.Server.WebListener": "1.0.0-beta3" in the dependencies node of the project.json file. Step 2: Create an Aciton Filter to output a line of text before and after the Action is executed. The code is as follows:
Step 3: Register the Action Filter in the ConfigureServices method
Run the program and access the corresponding path. All three types of code will output content as planned. The output content is as follows:
Ordinary ASP.NET 5 programs and MVC programs can be mixed together to use the Routing function. Customizing Routes ASP.NET 5 and MVC6 both provide a wealth of Route customization features. For the customization of common Route, you can refer to the DebuggerRouteHandler in the previous section. This method requires implementing your own HTTP output, which is equivalent to the original lightweight IHttpHandler. In this section, we will use this Route customization feature based on MVC, that is, the defined Route handler is MvcRouteHandler. In previous versions of MVC, to customize Route, you generally inherit from the RouteBase base class or the Route class; in the new version of MVC6, there are three ways to implement custom Route, as follows: Inherits from TemplateRoute Implementing IRouter Implement INamedRouter (Note: The only difference between INamedRouter and IRouter is that it has an additional name) In this example, we take the inheritance of TemplateRoute as an example. First, we create a subclass PromoTemplateRoute that inherits from this class. This class only matches the path under the /promo directory.
For ease of use, we also create some extension methods, as shown below: public static class RouteBuilderExtensions { public static IRouteBuilder MapPromoRoute(this IRouteBuilder routeCollectionBuilder, string name, string template) { MapPromoRoute(routeCollectionBuilder, name, template, defaults: null); return routeCollectionBuilder; } public static IRouteBuilder MapPromoRoute(this IRouteBuilder routeCollectionBuilder, string name, string template, object defaults) { return MapPromoRoute(routeCollectionBuilder, name, template, defaults, constraints: null, dataTokens: null); } public static IRouteBuilder MapPromoRoute(this IRouteBuilder routeCollectionBuilder, string name, string template, object defaults, object constraints, object dataTokens) { var inlineConstraintResolver = routeCollectionBuilder.ServiceProvider.GetService When using it, it is very simple, and is very similar to the previous method. The example is as follows:
In this way, we can use the PromoTemplateRoute class to handle some custom logic when the route matching conditions are met, such as adding some additional file header information and so on. Attribute-based Routing Attribute-based routing has always been a feature that MVC has been looking forward to, and has been implemented in Web API through RoutePrefix (used on Controller) and Route (used on Action). This feature has been rewritten and enhanced in MVC 6, and since MVC and Web API are combined into one, this feature can be used on both Controllers. For example:
Define a bookhome prefix on the above Controller, and define action names on About and Contact respectively, so the access addresses of the above three Actions are as follows
Here, we need to note that the Attributes used by Controller and Action are both Route. At the same time, inline parameters can still be used in these route template strings. For example, we can define routes like this:
Controller and Action markers In addition, the template string for Route not only supports inline parameters, but also supports the markers of Controller and Action, that is, instead of hard-coding the name of the Controller or Action, a character [controller] or [action] can be used to represent the name of the Controller or Action. For example, we can define a route like this on the Controller (nothing is defined on the Action):
In this way, the address to access the homepage becomes: /book/Home/Index. Equivalent Route definition for Web API In Web API, we usually need to define request methods such as GET and POST. For convenience, the new version of HTTPGET and other methods have integrated the Route function. You can directly pass the Route template into the constructor. The example is as follows:
The above Route definition indicates that it must comply with the routing rule of products/{productId:int} and must be a GET request. In fact, the HTTPGET series of attributes can also be used on ordinary MVC Controllers, because in MVC6, MVC Controller and Web API Controller are the same thing, except that the return type of MVC is IActionResult. Route definition not only supports GET requests, but also supports other types of requests such as POST, that is, there is no restriction on the request method. The HttpXXX series of features also support inline parameters and [controller] and [action] tags, so you can use them with confidence. Currently available feature classes are: HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch. Important Route Definition Rules Attribute-based route definition is convenient, but also dangerous. The specific rules and dangers are as follows. Rule 1: Defining Route attributes on a Controller is dangerous Once you define the Route attribute on a Controller, all routing rules under that Controller are not controlled by other rules. For example, if you define something like this
Then, you can no longer access the above two actions, because the default action name does not work at all, that is, the two paths /book/index and /book/about cannot be routed to the corresponding action methods. And /book cannot be accessed either, because there are more than two actions, and the system cannot locate one of them. Therefore, to make the above Action accessible, you must define a Route on one of the Actions, for example:
In this way, you can access the About method through /book/about, and access /book to access the default index method, because the index method is the only default method that does not define a route, so it is the default Action of the /book routing rule. If there are three Actions, you must define Routes for at least two Actions, as shown below:
At this point, the Contact method is the default /book route action. If you access the /book path, the page corresponding to Contact will be displayed. Rule 2: Route and HttpGet can be used together, but it is also dangerous We mentioned earlier that you can use either the Route feature or the HttpGet feature on an Action. The difference between the two is that there is an additional Http Method. Many students may ask if there will be any problems when using the two features together? In fact, these two features can be used together, as shown below:
In this way, both URLs /book/contact and /book/home/contact2 can be accessed. However, if HttpGet is defined here, the situation will be different. The example is as follows:
At this time, the way to access the Action is either to access the /book/contact address in GET mode or to access /book/home/contact2 in POST mode. So in order to avoid errors, it is recommended not to mix the two when using them. Even if you want to support both GET and POST, it is recommended to use the same type of HttpXXX to define these routes, for example:
This way, it looks much clearer. Rule 3: Multiple Route and multiple HttpXXX can also be used together, but it is also dangerous In the following example, we define 2 Route attributes for HomeController, and 2 Route attributes and 1 HttpPost attribute for Contact.
Then, after the above code takes effect, we will have six ways to access the Action, which are distributed as follows: GET: /book/contact GET: /book/contactus GET: /tom/contact GET: /tom/contactus POST: /book/home/contact2 POST: /tom/home/contact2 However, in the view file, if you generate a link address through @Html.ActionLink("Contact", "Contact", "Home"), the first defined Route will be used by default. If you want to force a specified order, you can use the Order property to define the sort value. By default, the smallest value will be used first. The example is as follows:
Custom inline parameter constraints In the previous introduction, we know that any type of routing supports different inline parameter constraints when defining, because these constraints are based on ASP.NET 5, not MVC6, and these constraints can still be extended. In this section, we will see how to customize some extensions. No parameter constraints First, let's look at a relatively simple constraint, that is, a parameterless constraint, similar to a type constraint such as {productId:int}. Suppose we want to implement an AABBCC string-limited constraint, as shown below:
In order to ensure that /index/112233 and /index/aabbcc meet the constraints, and /index/aabbccdd does not meet the constraints, we must first customize a constraint class AABBCCRouteConstraint and implement the IRouteConstraint interface. The example is as follows:
In this implementation class, you need to implement the Match method to determine whether the various parameters passed in meet the defined constraints and return true or false. In the parameters of the Match method, routeKey is the parameter name corresponding to the constraint {productId:aabbcc} (productId in this case), and the values collection will contain the number corresponding to the productId (such as 112233). This method returns true and false through the response judgment. The next step is to register the constraint class to the constraint collection of the Routing system. In the ConfigureServices method of Startup.cs, execute the following statement:
Note that the aabbcc registered here is the constraint name we specified earlier. After completing the above steps, you can implement functions similar to {productId:int}. With parameter constraints In general, you may need to define some constraint values, such as Length(1,10) to represent the string length between 1 and 10. For example, if we want to define a constraint rule with 4 parameters, such as abcd(1,10,20,30) to represent a special verification item, we need to declare a constructor with 4 parameters. The example is as follows:
Suppose you define the following constraints on the Action:
Then, after registering the constraint type, when the system starts thick scanning all routes for registration, it will analyze the four values you defined, and then assign these four values to the four attributes A, B, C, and D on the constraint instance corresponding to the route, so that when an HTTP request comes in, the value on the URL can be analyzed to see if it meets the rules defined in Match (these four attribute values can be used during verification). For all the default constraint codes, please refer to: https://github.com/aspnet/Routing/tree/dev/src/Microsoft.AspNet.Routing/Constraints In addition, if four parameter constraints are defined, the data type of the parameter must be met when defining the route on the action. If it does not meet the requirements, an error will occur when the system starts. The example error is as follows:
If the parameter type you define is a string type, the following two forms of definitions are both legal:
Although the routing of ASP.NET 5 and MVC6 is simple to use, the related usage rules are very complicated and you need to pay more attention when using them. |
<<: Decoding the story behind Google's online empire
A fierce battle broke out between WeChat and Appl...
The November sale is just around the corner, and ...
A while ago, WeChat released version 8.0, which w...
With the relaxation of the two-child policy and t...
SEO Strategy [6 lessons] Features of this section...
Anyone who has been in this industry for three to...
Many people rely on exercise to lose weight, but ...
iOS componentization was once a hot topic in the ...
Someone talked about his understanding of CPU on ...
When the crab is served, the navel is first opene...
If new energy vehicles start charging tolls, woul...
Reviewer of this article: Chen Haixu, Deputy Dire...
Everyone knows that Douyin accounts are divided i...
Thanksgiving is here. For Americans, Thanksgiving...
At a time when Generation Z, who are willing to s...