Analysis of advanced Series--WEBAPI routing mechanism of C #: Are you ready?

Source: Internet
Author: User

Original: http://www.cnblogs.com/landeanfen/p/5501490.html

From MVC to WEBAPI, the routing mechanism is always an important part of these technologies.

It can be very simple: if you just need to use some simple routes, such as/home/index, then you just need to configure a default route can be easily done;

It can be very mysterious: your URL can be changeable, see some seemingly "unreasonable" url, it is difficult to understand how it found a matching action, such as/api/user/1/detail, such a URL can make you tangled half a day.

It can be very obscure: when the interviewer asks "simply analyze the principles of the MVC routing mechanism," you may have prepared the answers beforehand, Then the crackling (type: urlroutingmodule→routes→routedata→requestcontext→controller), you may answer very fluently, but do not necessarily understand the meaning of these objects. Two years ago, the blogger did the interview.

Bloggers feel that the routing mechanism in your impression on which side, depends entirely on your curiosity. The routing mechanism is broad and profound, bloggers do not fully understand, but Bo is a curious person, always feel that the mysterious things have to explore a really. Today, bloggers according to their own understanding, sharing the webapi inside the routing principle and use, if not considered, welcome to the park friends to correct.

WEBAPI Series Articles

    • C # Advanced Series--webapi Interface test tool: Webapitestclient
    • C # Advanced Series--webapi cross-domain problem solution: CORS
    • C # Advanced Series--webapi Identity Authentication solution: Basic BASIC Certification
    • C # Advanced Series--WEBAPI Interface transfer parameter no longer confused: The explanation of the transfer parameter
    • C # Advanced Series--webapi interface return value not confused: return value type detailed
    • C # Advanced Series--webapi Exception handling solution
    • Analysis of advanced Series--WEBAPI routing mechanism of C #: Are you ready?
    • C # Advanced Series--webapi Regional Area usage Summary
One, MVC and WEBAPI routing mechanism comparison 1, MVC inside the route

In MVC, the default routing mechanism is to match the corresponding action method through the URL path, such as the URL of/home/getuser, which means matching the GetUser method under the controller of Home, which is very well understood, Because there is a default route defined in MVC, there is a RouteConfig.cs file under the App_start folder

    public class Routeconfig    {public        static void RegisterRoutes (RouteCollection routes)        {            routes. Ignoreroute ("{resource}.axd/{*pathinfo}");            Routes. MapRoute (                name: "Default",                URL: "{controller}/{action}/{id}",                defaults:new {controller = "Department", Action = "Index", id = urlparameter.optional}            );        }    }

URL: "{controller}/{action}/{id}" this defines the rules for our URLs, {controller}/{action} defines the required parameters for the route, {ID} is an optional parameter

2, Webapi inside the route

And the route in MVC is a bit different, thedefault route of Webapi is to match the corresponding action by means of HTTP (get/post/put/delete), that is, the default route of Webapi does not need to specify the name of the action. Or look at its default routing configuration, we create a new WEBAPI project that automatically generates a WebApiConfig.cs file under the App_start folder:

    public static class Webapiconfig    {public        static void Register (httpconfiguration config)        {            //Web API Routing            CONFIG. Maphttpattributeroutes ();            Config. Routes.maphttproute (                name: "Defaultapi",                routetemplate: "Api/{controller}/{id}",                defaults:new {id = Routeparameter.optional}            );        }    }

Similar to MVC, Routetemplate: "Api/{controller}/{id}" that defines a route template, Api/{controller} is a required parameter, {ID} is an optional parameter, then the problem comes, If our URL does not contain the name of the action, how do I find the requested method? Let's take a quick look at an example:

    public class Ordercontroller:apicontroller    {        [httpget] public        object GetAll ()        {            return ' Success ";        }    }

We use URLs to access

Indicates that the request succeeded.

Why is this request successful? That's because, when we visit the Http://localhost:21528/api/Order path, the WEBAPI routing engine automatically matches the "Api/{controller}/{id}" template, So I found the controller is Order this, then the question comes? How does it navigate to the GetAll () method? This is different from MVC, as mentioned earlier, WEBAPI's routing rule is to match the corresponding action through the HTTP method, then, when we access the path through the browser Http://localhost:21528/api/Order, The browser by default access to the URL is a GET request, so the WEBAPI routing engine will find the order of the controller inside the GET request method, because there is no parameters, so automatically match to the parameterless GET request →getall () method, so the request succeeds!

Of course, WEBAPI also supports the routing mechanism within MVC, but the restful style of service requires that the requested URL cannot contain an action, so the MVC routing mechanism is not advocated in Webapi.

This is one of the simplest examples, let's take a closer look at the routing principle and use in Webapi.

Ii. Webapi Routing Basics 1, default route

As we mentioned above, when you create a new WEBAPI service, a default route is automatically generated in the WebApiConfig.cs file:

            Config. Routes.maphttproute (                name: "Defaultapi",                routetemplate: "Api/{controller}/{id}",                defaults:new {id = Routeparameter.optional}            );

To go to the definition of the Maphttproute () method, it has four overloaded methods:

Take a look at each parameter's role:

    • Name: "Defaultapi" → indicates the name of this route, just make sure the routing name is not duplicated.
    • Routetemplate: "Api/{controller}/{id}" → means the URL rule for routing, "API" is a fixed part, mainly used to identify the URL of the current request is an API service interface, different MVC route, of course, here is not necessarily written " API ", if you change to" Apiserver ", then you request the URL also need to write" Apiserver "," {controller} "is a placeholder part of the controller, in the real URL, the part corresponding to the specific controller name, This is consistent with MVC; "{ID}" is the placeholder part of the parameter, which indicates the parameter, which is usually set in default. With this URL of the routing template constraint request, for example: the URL we requested is written as Http://localhost:21528/Order, then there must be no corresponding route, because the "API" parameter must be selected. If the requested URL does not match the corresponding route, a 404 status Code is returned to the client.
    • defaults:new {id = routeparameter.optional}→ represents the default value for the route, such as the Routetemplate,{controller} and {id} sections above, you can set the default value. For example: defaults change to new {controller= "Order", id = routeparameter.optional}, then we request http://localhost:21528/ API This URL can still access the GetAll () method.
    • constraints→ represents a routing constraint and is generally a regular expression that constrains the routing template. For example: We join the constraint constraints:new {id = @ "\d+"}, which means that the constraint must match one or more parameter IDs, so we add another method to the Ordercontroller
    public class Ordercontroller:apicontroller    {        [httpget] public        object GetAll ()        {            return ' Success ";        }        [HttpGet]        public object GetById (int id)        {            return ' Success ' + id;        }    }

We visit through HTTP://LOCALHOST:21528/API/ORDER/2 to get the result:

We then visit through http://localhost:21528/api/Order/a to get the result:

This is well understood, and the value of the ID does not match the regular expression.

And we visited Http://localhost:21528/api/Order. Results:

Even the GetAll () method can not be found. What is this for? This is the constraint in the mischief, the regular \d+ to match one or more numbers, so if the requested URL does not pass the number, it will automatically match. So, if we need to match the non-parametric method, we change the constraint to this: constraints:new {id = @ "\d*"}, which means matching 0 or more digits, try again

This will be OK.

Said so many are constraint ID, in fact you can also use expressions to constrain Controller, action and so on, but generally not commonly used, we do not do too much to explain.

2. Custom Routing

So many of these are introduced in the default routing principle. In addition to the default route, we can also customize the route, we will change the WebApiConfig.cs inside to this:

    public static class Webapiconfig    {public        static void Register (httpconfiguration config)        {            //Web API Routing            CONFIG. Maphttpattributeroutes ();            1. Default route            config. Routes.maphttproute (                name: "Defaultapi",                routetemplate: "Api/{controller}/{id}",                defaults:new {id = Routeparameter.optional}            );            2. Custom Route One: match to Action            Config. Routes.maphttproute (                name: "Actionapi",                routetemplate: "Actionapi/{controller}/{action}/{id}",                defaults:new {id = routeparameter.optional}            );            3. Custom route two            config. Routes.maphttproute (                name: "Testapi",                routetemplate: "Testapi/{controller}/{ordertype}/{id}",                defaults:new {ordertype= "AA", id = routeparameter.optional}            );        }    }

In addition to the default route, we add two more custom routing rules

2.1. Custom Route One: match to Action

The first custom route is well understood, consistent with the routing mechanism inside MVC, but to differentiate the default route, we change the prefix of the routing template to "Actionapi". We can also find a matching method with this custom route.

For example, we visit http://localhost:21528/actionapi/Order/GetAll and get the result:

Matching by the name of the action is well understood, the above getall () is the method name, WEBAPI will default it is the name of the action, if you want the method name and action name inconsistent, you can also customize the name of the action, This can be achieved through the feature ActionName, as follows:

        [ActionName ("Testactionname")]        [HttpGet]        public object GetById (int id)        {            return "Success" + ID;        }

Test results:

Before the blogger demonstrates the parameters and return values, it is used to match the route to the action. This usage is consistent with MVC and is better understood, but Webapi does not advocate it.

2.2. Custom Route Two

The second custom route first glance seems to be not well understood, okay, let's start by using its routing template rules to try.

Match to GetAll () method by http://localhost:21528/testapi/Order/aa/

The GetByID () method is matched by HTTP://LOCALHOST:21528/TESTAPI/ORDER/AA/2

The GetByID () method is also matched by HTTP://LOCALHOST:21528/TESTAPI/ORDER/BB/2.

What do you mean? That is, as long as {OrderType} is configured according to the routing rules, the corresponding method can be found. What's the use of {OrderType} here? This is to be explained in the following description of feature routing.

3. Routing principle

With these theories as the basis, we will analyze the principle of the routing mechanism and the route matching process in Webapi. Since WEBAPI's routing mechanism and MVC have many similarities, to understand the WEBAPI routing mechanism, it is necessary to move out the objects in the ASP. NET Rounting. The process is a bit complicated, and bloggers are making some of the main processes according to their own understanding:

1. After the WEBAPI service is started, the global configuration file Global.asax.cs protected void Application_Start () {globalconfiguration.configure ( Webapiconfig.register);} method, the public static voidregister (httpconfiguration config) in the WebApiConfig.cs is executed by a parameter delegate to add all the configured routing information to the Httproutecollection objects (which may be routcollection objects in MVC) are saved. The instance name of the Httproutcollection object here is routes, which is important to use later .

2, when we send the request to the WEBAPI server, such as when we visit Http://localhost:21528/api/Order this URL, the request will first be intercepted by UrlRoutingModule monitoring components, and then, The intercepted request is matched to the corresponding route template in the Routes route collection (returns 404 if the corresponding route template is not matched), and the corresponding Ihttproute object is obtained. The Ihttproute object is an entity that matches within the routes collection.

3, the Ihttproute object to the current request of the context object RequestContext processing, according to the Ihttproute object inside the URL matching to the corresponding controller, and then based on the type and parameters of the HTTP request to find the corresponding action. Such a request will be able to find the corresponding method.

The process itself is very complex, in order to simplify, the blogger chose only the most important process. A more detailed routing mechanism can be consulted: http://www.cnblogs.com/wangiqngpei557/p/3379095.html. This article is written a bit deep, interested can see.

Third, WEBAPI routing process

Through the process of routing above, we know that after a request comes in, the route needs to go through three stages.

    1. Match the routing template based on the requested URL
    2. Locate the Controller
    3. Find action
1. Match the routing template according to the requested URL

This has been said a lot, mainly is the routing template configuration and URL matching. There is no explanation for this.

2. Locate the Controller

If you decompile the code of the routing module, you will find that the controller selection is mainly handled in the Selectcontroller () method of the Ihttpcontrollerselector interface.

This method passes the current request to the Httprequestmessage object as a parameter and returns the Httpcontrollerdescriptor object. This interface is provided by default by the Defaulthttpcontrollerselector class.

The approximate algorithm mechanism in the default implementation is to first locate the actual controller name (such as "Order") in the routing dictionary, and then add the string "controller" to the name of the request controller (such as "Ordercontroller") Finally, we find the controller of the corresponding WEBAPI, and instantiate it to get the control object of the current request.

3. Find action

After the controller object is obtained, the API engine matches the action by calling the SelectAction () method of the Ihttpactionselector interface. This process mainly includes:

    • Parse the current HTTP request to get the request type (get, post, put, or delete)
    • If the routing template is configured with {action}, it is taken directly to the action name inside the URL
    • Parse the parameters of the request

If the routing template is configured with {action}, it is easy to find the corresponding action, and if you do not configure the action, it will first match the request type (Get/post/put/delete, etc.) and then match the request parameters to find the corresponding action. Let's look at an example, for example, our controller adds the following methods.

    public class Ordercontroller:apicontroller    {        [httpget] public        ihttpactionresult GetAll ()        {            Return ok<string> ("Success");        }        [HttpGet]        Public Ihttpactionresult GetById (int id)        {            return ok<string> ("Success" + ID);        }        [HttpPost]        Public httpresponsemessage postdata (int id)        {            return request.createresponse ();        }        [HttpPost]        Public Httpresponsemessage Savadata (order order)        {            return request.createresponse ();        }        [Httpput]        Public Ihttpactionresult Put (int id)        {            return Ok ();        }        [Httpdelete]        Public Ihttpactionresult Deletebyid (int id)        {            return Ok ();        }    }

Match the result of the action

URL http Method Parameters Results
Http://localhost:21528/api/Order Get None Match GetAll Method
Http://localhost:21528/api/Order Get Id Match GetByID Method
Http://localhost:21528/api/Order Post Order Match Savadata Method
Http://localhost:21528/api/Order Put Id Match the Put method
Http://localhost:21528/api/Order Delete Id Match Deletebyid Method

WEBAPI also provides an action request that supports multiple HTTP methods simultaneously, using the Acceptverbs feature to tag. But bloggers feel that the actual use is not much, interested can understand the next.

        [Acceptverbs ("GET", "POST")]        Public Ihttpactionresult GetById (int id)        {            return ok<string> ("Success" + ID);        }
Iv. WEBAPI Feature Routing

It says so much is a number of global configurations for routing. And there are problems:

If the HTTP request is the same method (for example, it is a POST request), and the requested parameters are the same. This time seems to be a little too good to do, this situation in the actual project is still more. Like what

public class Ordercontroller:apicontroller    {        //order scheduling        [httppost] public        void Orderproduct ([frombody] String strpostdata)        {        }        //order cancellation        [httppost] public        void Ordercancel ([frombody]string Strpostdata)        {                    }        //order deletion        [httppost] public        void Orderdelete ([frombody]string strpostdata)        {                   }    }

This is not a problem that can be solved by using the restful style of routing that we've talked about. Of course, a park friend may have said, in this case, we add "{action}" in the routing template is not done! This is really feasible. But it is still the same sentence, not advocated. Let's take a look at how to use feature routing to solve this problem.

1. Start feature routing

If you want to use attribute routing, you must first enable attribute routing in the WebApiConfig.cs register method:

        public static void Register (httpconfiguration config)        {            //Enable Web API feature Routing            config. Maphttpattributeroutes ();            1. Default route            config. Routes.maphttproute (                name: "Defaultapi",                routetemplate: "Api/{controller}/{id}",                defaults:new {id = Routeparameter.optional}            );        }

In general, when we create a new WEBAPI project, we automatically add this sentence to the Register method.

2. The simplest feature routing

We're adding this action to the Ordercontroller controller.

        [Route ("Order/savedata")]        [HttpPost]        Public Httpresponsemessage Savadata (order order)        {            return request.createresponse ();        }

Then we call through the Ajax inside the web

$ (function () {    $.ajax ({        type: ' Post ',        URL: ' http://localhost:21528/Order/SaveData ',        data: {id:2, NO: "AAA"},        success:function (data, status) {            alert (data);        }    );});

Get results:

Of course, some people may have doubts, the function of this feature is the same as the "{action}" function, otherwise, if it is changed to [Route ("Test/attrroute")], and then the requested URL is replaced by http://localhost : 21528/test/attrroute, you can find the corresponding action.

The purpose of attribute routing is to solve problems that our public routing template engine cannot solve. Once an action defines an attribute route, it can be found by routing rules above the attribute route.

3. Characteristic routing with parameters

The rules for attribute routing can use the "{}" placeholder to dynamically pass parameters, such as we have a feature that routes

        [Route ("Ordertype/{id}/order")]        [HttpGet]        Public Ihttpactionresult GetById (int id)        {            return ok<string> ("Success" + ID);        }

Call inside the browser

The call succeeded. In this, we can understand the "weird" route →/api/user/1/detail this article at the very beginning.

4. Constraints and default values for parameters
        [Route ("Api/order/{id:int=3}/ordertype")]        [HttpGet]        Public Ihttpactionresult GetById (int id)        {            return ok<string> ("Success" + ID);        }

The value of the constraint variable part {ID} must be of type int. And the default value is 3.

Look at the effect

If the constraint is not met, 404 is returned directly.

5. Route Prefix

In a formal project, all attribute routes for all actions of the same controller identify an identical prefix, which is not required, but can increase the readability of the URL. The general practice is to use the feature [Routeprefix] to identify the controller.

[Routeprefix ("Api/order")]    public class Ordercontroller:apicontroller    {        [Route ("]]        [httpget] public        ihttpactionresult GetAll ()        {            return ok<string> ("Success");        }        [Route ("{id:int}")]        [HttpGet]        Public Ihttpactionresult GetById (int id)        {            return ok<string> ("Success" + ID);        }        [Route ("PostData")]        [HttpPost]        Public httpresponsemessage postdata (int id)        {            return request.createresponse ();        }    }

Then the action of this controller requires the/api/order to start, followed by the action attribute routing rules.

Five, the first restful style of WEBAPI service

Through the above, we can construct a restful style of WEBAPI service.

  [Routeprefix ("Api/attrorder")] public class Ordercontroller:apicontroller {[Route ("")] [HttpGet]        Public Ihttpactionresult GetAll () {return ok<string> ("Success");            } [Route ("{Id:int=3}/orderdetailbyid")] [HttpGet] public ihttpactionresult GetById (int id) {        Return ok<string> ("Success" + ID);            } [Route ("{No}/orderdetailbyno")] [HttpGet] public ihttpactionresult Getbyno (string no) {        Return ok<string> ("Success" + No);        } [Route ("{name}/orderdetailbyname")] [HttpGet] public ihttpactionresult getbyname (string name)        {return ok<string> ("Success" + name); } [Route ("PostData")] [HttpPost] public httpresponsemessage postdata (int id) {Retu        RN Request.createresponse (); } [Route ("Test/attrroute")] [HttpPost] public HttpResponsemessage Savadata (Order order) {return request.createresponse (); }    }

Get results

Vi. Summary

After all this time, it's all over. If you think this article is helpful to you, please help Bo main recommendation , your support is the biggest power of Bo master!

Category: C # Tags: Webapi recommended Follow me collection this article lazy
Follow-30
Fans-710 + plus attentionpay attention to the landlord bar the1You have recommended «previous: C # Advanced Series--webapi interface return value not confused: return value type detailed

Analysis of advanced Series--WEBAPI routing mechanism of C #: Are you ready?

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.