Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of Routing routing in ASP.NET5 and MVC6

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

Editor to share with you the example analysis of Routing routing in ASP.NET5 and MVC6. I believe most people don't know much about it, so share this article for your reference. I hope you can learn a lot after reading this article. Let's learn about it together.

Functional introduction of the new version of Routing

In ASP.NET5 and MVC6, the Routing function has been completely rewritten, although the usage is similar, but it is completely different from the previous Routing principle. The Routing framework can support not only MVC and Web API, but also general ASP.NET5 programs. The changes to the new version have the following parts.

First of all, the Routing system is based on ASP.NET 5 and is a routing framework independent of MVC, not based on MVC. MVC just extends a shortcut to it.

Second, in ASP.NET 5, there is no difference between the MVC and Web API controllers, that is, the two are merged into one. Both derive from the same Controller base class. That is to say, the Routing framework is applicable to both, and to MVC means that it also applies to Web API.

Finally, inline constraints and parameter options are available for both convention-based Route declarations and Attribute-based Route declarations. For example, you can specify the data type of a parameter in the route, mark a parameter as optional, or provide it with a default value.

The main processes of the Routing framework

The basic Routing framework is implemented based on Middleware, so it can be added to HTTP's request Pipeline, and it can be combined with any other Middleware, such as static file handlers, error pages, or SignalR servers.

Before using the Routing framework, the first thing to understand is the role of Routing, which is simple:

For HTTP requests, the Routing system is responsible for finding the matching route, creating route data, and dispatching the request to the Handler of the route. The choice of Controller and Action is just a concrete implementation of MVC's Handler, which uses route data and other information in the HTTP request to select the Controller and Action to execute. In the new version of MVC6, the handler's name is MvcRouteHandler.

The implementation of the routing system is as follows:

ASP.NET 5 monitored a HTTP request. Routing Middleware then tries to match the route in the route collection to the request. Once a request is successfully matched, the handler corresponding to the route is found. Call the RouteAsync method on the handler (because all handler implement the interface method). RoutingContext has an IsHandled tag, which, if set to true, means that the request has been successfully processed by the handler; if set to false, it means that the handler cannot process the request, and the system will match another route for this.

Unlike the previous Routing system, once the old Routing system successfully matches a route, it will be handed over to its corresponding Handler, regardless of whether the corresponding Handler can handle the request or not, so there will be a successful route match, but the corresponding action will not be found, and a 404 error will occur. The new version makes the improvement in step 4 above (return control to the Routing system for re-matching) It still looks very good.

Improvement of Route parameters and constraints

In the previous route setting, to constrain the data type of a parameter, we needed the following code:

Routes.MapRoute ("Product", "Product/ {productId}", defaults: new {controller = "Product", action = "Details"}, constraints: new {productId = @ "\ d +"})

In the new version of route, you can set Product/ {productId:int} directly, and the constraints follow the following conventions:

{parameter:constraint}

The following constraints are currently supported:

The constraint example shows that the parameter required "Product/ {ProductName:required}" must match the letter alpha "Product/ {ProductName:alpha}". Int "Product/ {ProductId:int}" match int type long "Product/ {ProductId:long}" match long type bool "Product/ {ProductId:bool}" match bool type double "Product/ {ProductId:double}" match double type float "Product/ {ProductId:float}" match float class type guid "Product/ {ProductId:guid}" match guid type decimal "Product/ {ProductId:decimal}" match decimal type datetime "Search/ {datetime:datetime}" Match datetime type composite "Product/ {ProductId:composite}" match composite type length "Product/ {ProductName:length (5)}" length must be 5 character length "Product/ {ProductName:length (5) 10)} "maxlength" Product/ {productId:maxlength (10)} "maximum length is 10minlength" Product/ {productId:minlength (3)} "minimum length is 3min" Product/ {ProductID:min (3)} "greater than or equal to 3max" Product/ {ProductID:max (10)} "less than or equal to 10range" Product/ {ProductID:range (5) 10)} "the corresponding array is between 5 and 10. Regex" Product/ {productId:regex (^\ d {4} $)} "matches the specified regular expression.

For optional parameters, the value needs to be followed by a question mark after the constraint type, as shown in the following example:

Routes.MapRoute ("Product", "Product/ {productId:long?}", new {controller = "Product", action = "Details"})

If the parameter is required and you need to keep a default value, you can set it according to the following example:

Routes.MapRoute ("Product", "Product/ {productId:long=1000}", new {controller = "Product", action = "Details"})

General Routing

With regard to the use of examples, we will not start with MVC, but with the normal use of Routing. When the new version of route is added, the TemplateRoute instance is added by default, and a Handler is set when the instance is instantiated.

For example, let's first create an empty ASP.NET 5 project and add the assembly "Microsoft.AspNet.Routing": "1.0.0-beta3" to the dependencies node of the project.json file, and add the following code to the Configure method of Startup.cs:

Public void Configure (IApplicationBuilder app) {RouteCollection routes = new RouteCollection (); routes.Add (new TemplateRoute (new DebuggerRouteHandler ("RouteHandlerA"), ", null)); routes.Add (new TemplateRoute (new DebuggerRouteHandler (" RouteHandlerB ")," test/ {a} / {b:int} ", null)); routes.Add (new TemplateRoute (new DebuggerRouteHandler (" RouteHandlerC ")," test2 ", null)); app.UseRouter (routes); / / enable Routing function}

Here, we set the Handler processed by the HTTP request to DebuggerRouteHandler, which inherits from IRouter. The example code is as follows:

Public class DebuggerRouteHandler: IRouter {private string _ name; public DebuggerRouteHandler (string name) {_ name = name;} public string GetVirtualPath (VirtualPathContext context) {throw new NotImplementedException ();} public async Task RouteAsync (RouteContext context) {var routeValues = string.Join ("", context.RouteData.Values); var message = String.Format ("{0} Values= {1}", _ name, routeValues); await context.HttpContext.Response.WriteAsync (message); context.IsHandled = true;}}

The above class, after inheriting from IRouter, must implement a method of RouteAsync, and if the processing is successful, set IsHandled to true.

You can view the results by visiting the following URL:

Normal: `http://localhost:5000/` normal: `http://localhost:5000/test/yyy/12`404: `http://localhost:5000/test/yyy/s` normal: `http://localhost:5000/test2`404: `http://localhost:5000/test3`

Note: both TemplateRoute and DebuggerRouteHandler inherit from IRouter and are at the core of implementing the aforementioned 404 error-free (continuing to match 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 route when calling the app.UseMVC method. Here we take a blank project as an example to see how MVC's route is used.

Step 1: reference the assembly "Microsoft.AspNet.Mvc": "6.0.0-beta3" in the dependencies node of the project.json file

Part 2: add Middleware for MVC, use MVC, and then add a default route, as follows:

Public void ConfigureServices (IServiceCollection services) {services.AddMvc ();} public void Configure (IApplicationBuilder app) {app.UseMvc (routeBuilder = > {routeBuilder.MapRoute (name: "default", template: "{controller} / {action} / {id?}", defaults: new {controller = "Home", action = "Index");});}

Step 3: create the following three kinds of Controller, where ProductsController inherits from Controller under Microsoft.AspNet.Mvc.

Public class ProductsController: Controller {public IActionResult Index () {return Content ("It Works with Controller Base Class!");}} public class DemoController {public IActionResult Index () {return new ObjectResult ("It Works without Controller Base Class!");}} public class APIController {public object Index () {return new {Code = 100000, Data = "OK"};}}

When you access http://localhost:5000/products and http://localhost:5000/demo, you can display normal output, while when you access http://localhost:5000/api, you return json data.

This is the combination of MVC and API as we mentioned in the previous ASP.NET5 new features, and it is also possible not to inherit from the Controller base class (but the class name ends with Controller). At the heart of this technique is Controller's lookup mechanism. For information on how to find the right assembly in a project, please refer to the "Controller and Action" section.

The new version of MVC has two conditions when determining Controller: it either inherits from Controller or 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 the relevant context (such as HTTPContext, ActionContext, etc.), you do not need to inherit from the Controller base class; but the recommendations inherit from Controller, because you can make more use of the methods and properties of the base class, because all the Controller classes you define have to go through the lifecycle of MVC, regardless of inheritance or not. Let's verify it through ActionFilter:

Step 1: 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 and output a line of text before and after Action execution, with the following code:

Public class ActionFilterTest: IActionFilter {public void OnActionExecuting (ActionExecutingContext context) {var typeName = context.Controller.GetType (). FullName; Console.WriteLine (typeName + "." + context.ActionDescriptor.Name + ": Start");} public void OnActionExecuted (ActionExecutedContext context) {var typeName = context.Controller.GetType (). FullName; Console.WriteLine (typeName + "." + context.ActionDescriptor.Name + ": END");}}

Step 3: register the Action Filter in the ConfigureServices method.

Services.Configure (options = > {options.Filters.Add (typeof (ActionFilterTest));})

Run the program and access the path of the response. All three types of code will output the content as planned, as follows:

RouterTest.ProductsController.Index:StartRouterTest.ProductsController.Index:EndRouterTest.DemoController.Index:StartRouterTest.DemoController.Index:EndRouterTest.APIController.Index:StartRouterTest.APIController.Index:End

Ordinary ASP.NET5 programs and MVC programs can mix and use Routing functions together.

Custom Route

Both ASP.NET 5 and MVC6 provide rich Route customization features. For customization of ordinary Route, you can refer to DebuggerRouteHandler in the previous section. In this way, you need to implement your own HTTP output, which is equivalent to the original lightweight IHttpHandler. In this section, we will define this Route customization feature based on MVC, that is, the Handler handlers of the defined Route are all MvcRouteHandler.

In the previous version of MVC, custom Route was generally inherited from the RouteBase base class or Route class. In the new version of MVC6, there are three ways to implement custom Route, which are as follows:

Inherit from TemplateRoute implementation IRouter implementation INamedRouter (Note: the only difference between INamedRouter and IRouter is an extra name)

In this case, taking inheriting from TemplateRoute as an example, we first create a subclass PromoTemplateRoute that inherits from this class, which only matches the path under the / promo directory.

Public class PromoTemplateRoute: TemplateRoute {public PromoTemplateRoute (IRouter target, string routeTemplate, IInlineConstraintResolver inlineConstraintResolver): base (target, routeTemplate, inlineConstraintResolver: inlineConstraintResolver) {} public PromoTemplateRoute (IRouter target, string routeTemplate, IDictionary defaults, IDictionary constraints, IDictionary dataTokens, IInlineConstraintResolver inlineConstraintResolver): base (target, routeTemplate, defaults, constraints, dataTokens, inlineConstraintResolver) {} public PromoTemplateRoute (IRouter target, string routeName, string routeTemplate, IDictionary defaults, IDictionary constraints, IDictionary dataTokens IInlineConstraintResolver inlineConstraintResolver): base (target, routeName, routeTemplate, defaults, constraints, dataTokens, inlineConstraintResolver) {} public async override Task RouteAsync (RouteContext context) {var requestPath = context.HttpContext.Request.Path.Value? String.Empty; if (! requestPath.StartsWith ("/ promo", StringComparison.OrdinalIgnoreCase)) {return;} await base.RouteAsync (context);}}

For ease of use, we also create some extension methods by comparing the gourd with a ladle. Examples are as follows:

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 () RouteCollectionBuilder.Routes.Add (new PromoTemplateRoute (routeCollectionBuilder.DefaultHandler, name, template, ObjectToDictionary (defaults), ObjectToDictionary (constraints), ObjectToDictionary (dataTokens), inlineConstraintResolver); return routeCollectionBuilder;} private static IDictionary ObjectToDictionary (object value) {var dictionary = value as IDictionary; if (dictionary! = null) {return dictionary;} return new RouteValueDictionary (value);}}

When using it, it is very simple, very similar to the previous method, as shown in the following example:

Routes.MapPromoRoute (name: "default2", template: "promo/ {controller} / {action} / {id?}", defaults: new {controller = "Home", action = "Index"})

In this way, we can use the PromoTemplateRoute class to handle some custom logic when the route matching criteria are met, such as adding some additional header information, and so on.

Routing based on Attribute

Attribute-based Routing functionality has always been expected by MVC, and Web API has been implemented through RoutePrefix (for use on Controller) and Route (for use on Action). This feature has been rewritten and enhanced in MVC 6, and because MVC and Web API merge into one, it can be used on both Controller.

For example:

[Route ("bookhome")] public class HomeController: Controller {public IActionResult Index () {return View ();} [Route ("about")] public IActionResult About () {ViewBag.Message = "Your application description page."; return View ();} [Route ("contactus")] public IActionResult Contact () {ViewBag.Message = "Your contact page."; return View ();}}

A bookhome prefix is defined on the above Controller, and action names are defined on About and Contact respectively, so the access addresses of the above three Action are in the following form:

/ bookhome/bookhome/about/bookhome/contactus

Here, we need to note that the Attribute used by Controller and Action is Route, and in these route template strings, inline parameters can still be used, for example, we can define routes like this:

[Route ("products/ {productId:int}")]

Controller and Action tag bits

In addition, the template string for Route supports not only inline parameters, but also the tag bits of Controller and Action, that is, you do not have to write the name of the Controller or Action, but use a [controller] or [action] character to represent the name of the Controller or Action. For example, we can define a route like this on Controller (nothing is defined on Action):

[Route ("book/ [controller] / [action]")]

So the address that accesses the home page becomes: / book/Home/Index.

Equivalent Route definition of Web API

In Web API, we also define request methods such as GET and POST. For convenience, a series of methods such as the new version of HTTPGET integrate the Route feature, which can be directly passed into the Route template in the constructor. The example is as follows:

[HttpGet ("products/ {productId:int}")]

The above definition of Route means that both the routing rules of products/ {productId:int} and GET requests should be met.

In fact, HTTPGET this series of Attribute can also be used on ordinary MVC Controller, because in MVC6, MVC Controller and Web API Controller themselves 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 mode of requests. In the HttpXXX series features, inline parameters and [controller], [action] tag bits are also supported, so you can rest assured to use them. Currently available feature classes are: HttpGet, HttpPost, HttpPut, HttpDelete, HttpPatch.

Not important Route definition rules

The definition of Route based on Attribute is convenient, but also dangerous, the specific rules and hazards are as follows.

The Route feature is defined on the rule 1:Controller is dangerous.

Once the Route feature is defined on Controller, all routing rules under that Controller are not controlled by other rules, for example, if you define something like this

[Route ("book")] public class HomeController: Controller {public IActionResult Index () {return View ()} public IActionResult About () {ViewBag.Message = "Your application description page."; return View ();}}

Then, you will no longer be able to access the above two Action, because the default action name will not work at all, that is, the paths / book/index and / book/about cannot be routed to the corresponding Action method. And / book cannot be accessed because there are more than two Action and the system cannot navigate to one of the Action.

So for the above Action to be accessible, you must define a re-Route on one of the Action, for example:

[Route ("book")] public class HomeController: Controller {public IActionResult Index () {return View ();} [Route ("about")] public IActionResult About () {ViewBag.Message = "Your application description page."; return View ();}}

In this way, you can access the About method through / book/about, and access / book can access the default index method, because this index method is the only method that does not define a route by default, so it is the default Action of the / book routing rule. If you have three Action, you must define a Route for at least two Action, as shown in the following example:

[Route ("book")] public class HomeController: Controller {[Route ("index")] public IActionResult Index () {return View ();} [Route ("about")] public IActionResult About () {ViewBag.Message = "Your application description page."; return View ();} public IActionResult Contact () {ViewBag.Message = "Your contact page."; return View ();}

At this point, the Contact method is the Action of the default / book route, and if you visit the / book path, the page corresponding to Contact will be displayed.

The rules 2:Route and HttpGet can be used together, but they are also dangerous

As we mentioned earlier, you can use either the Route feature or the HttpGet feature on Action, and the difference between the two is that there is an extra Http Method. Many students can ask whether there will be any questions when the two features are used together.

In fact, these two features can be used together, as shown in the following example:

[Route ("book")] public class HomeController: Controller {[Route ("Contact")] [HttpGet ("home/Contact2")] public IActionResult Contact () {ViewBag.Message = "Your contact page."; return View ();}}

In this way, both / book/contact and / book/home/contact2 can be accessed. However, if HttpGet is defined here, the situation is different. The example is as follows:

[Route ("Contact")] [HttpPost ("home/Contact2")]

At this point, the way to access the Action is either to access the / book/contact address as GET or / book/home/contact2 as POST. Therefore, in order to avoid errors, it is recommended not to mix the two, even if you want to support both GET and POST, it is also recommended to use the same type of HttpXXX to define these routes, for example:

[HttpGet ("Contact")] [HttpPost ("home/Contact2")]

In 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 two Route features for HomeController, while Contact defines two Route features and one HttpPost feature.

[Route ("book")] [Route ("tom")] public class HomeController: Controller {[Route ("Contact")] [Route ("ContactUS")] [HttpPost ("home/Contact2")] public IActionResult Contact () {ViewBag.Message = "Your contact page."; return View ();}}

So, after the above code takes effect, we will have six kinds of access to the Action, which are distributed as follows:

GET:/book/contactGET:/book/contactusGET:/tom/contactGET:/tom/contactusPOST:/book/home/contact2POST:/tom/home/contact2

However, in the view file, if the link address is generated through @ Html.ActionLink ("Contact", "Contact", "Home"), the first defined Route is used by default, and if you want to force the order to be specified, you can use the Order attribute to define the sort value, and the lowest value is preferred by default. Examples are as follows:

[Route ("book", Order = 1)] [Route ("tom", Order = 0)] public class HomeController: Controller {[Route ("Contact", Order = 1)] [Route ("ContactUS", Order = 0)] [HttpPost ("home/Contact2", Order = 2)] public IActionResult Contact () {ViewBag.Message = "Your contact page."; return View ();}}

Custom inline parameter constraint

In the previous introduction, we know that any type of route supports different inline parameter constraints when defined, because these constraints are based on ASP.NET 5, not MVC6, and these constraints are extensible, so in this section we will look at how to customize some extensions.

No parameter constraint

First of all, let's look at a relatively simple constraint, that is, no parameter constraint, a type constraint like {productId:int}. Suppose we want to implement an AABBCC string qualified constraint, as shown in the following example:

[Route ("index/ {productId:aabbcc}")]

To ensure that / index/112233 and / index/aabbcc are in line with the constraints, while / index/aabbccdd is not, we first need to customize a constraint class AABBCCRouteConstraint and implement the IRouteConstraint interface. The example is as follows:

Public class AABBCCRouteConstraint: IRouteConstraint {public bool Match (HttpContext httpContext, IRouter route, string routeKey, IDictionary values, RouteDirection routeDirection) {bool b = false; object value; if (values.TryGetValue (routeKey, out value) & & value! = null) {if (value is string) / / get the passed value, such as aabbcc or 112233 {string aabbcc = value.ToString () B =! string.IsNullOrWhiteSpace (aabbcc) & & aabbcc.Length = = 6 & & aabbcc [0] = = aabbcc [1] & & aabbcc [2] = = aabbcc [3] & & aabbcc [4] = = aabbcc [5];}} return b;}

In this implementation class, to implement the Match method, determine whether it conforms to the defined constraint according to the various parameters passed in, and return one of the parameters of the true or false,Match method, where routeKey is the parameter name of the constraint {productId:aabbcc} (productId in this case), and the number corresponding to the productId will be found in the values set (such as 112233). In this method, true and false are returned through the judgment of response.

The next step is to register the constraint class with the constraint set of the Routing system, and in the ConfigureServices method of Startup.cs, execute the following statement:

Services.Configure (opt = > {opt.ConstraintMap.Add ("aabbcc", typeof (AABBCCRouteConstraint));})

Note that the aabbcc registered here is the name of the constraint we specified earlier, and after completing the above steps, you can implement a function similar to {productId:int}.

With parameter constraint

In general, some constraint values may need to be defined, such as Length (1Magne10) 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 to represent a special verification item, we need to declare a constructor with 4 parameters, as shown in the example:

Public class ABCDRouteConstraint: IRouteConstraint {public int A {get; private set;} public int B {get; private set;} public int C {get; private set;} public int D {get; private set;} public ABCDRouteConstraint (int a, int b, int c, int d) {A = a, b, int, d;} public bool Match (HttpContext httpContext, IRouter route, string routeKey, IDictionary values, RouteDirection routeDirection) {bool b = false; object value If (values.TryGetValue (routeKey, out value) & & value! = null) {var valueString = value.ToString (); / / further verification is needed here return true;} return b;}

Suppose you define the following constraints on Action:

[Route ("index/ {productId:abcd (1pm 20je 30je 40)}")]

Then, after registering the constraint type, when the system starts a thick scan of all the Route to register, it will analyze the four values you have defined, and then assign these four values to the A, B, C and D attributes on the corresponding constraint instance of the route, so that when the HTTP request comes over, analyze the values on the URL to see if they conform to the rules defined in Match (these four attribute values can be used during verification).

All the code for the default constraint can refer to: https://github.com/aspnet/Routing/tree/dev/src/Microsoft.AspNet.Routing/Constraints

In addition, if a constraint of four parameters is defined, the data type of the parameter must be matched when defining the route on the action. If not, an error will occur when the system starts up. The example error is as follows:

[Route ("index/ {productId:abcd}")] / / No argument-free constructor [Route ("index/ {productId:abcd (a)}")] [Route ("index/ {productId:abcd ('a')}")] / the input string is not in the correct format [Route ("index/ {productId:abcd)}") / / the number of parameters of the constructor is inconsistent with the number of parameters defined.

If the parameter type you define is a string type, the following two forms of definitions are legal:

[Route ("index/ {productId:abcd (a meme breco cjue d)}") [Route ("index/ {productId:abcd ('axie pyrrhenous pyrrhenous d')}")]

Although the route usage of ASP.NET 5 and MVC6 is very simple, the relevant usage rules are very complicated and people need to pay more attention when using them.

The above is all the contents of the article "sample Analysis of Routing routing in ASP.NET5 and MVC6". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report