preface
This article is quite long, it takes about 15 minutes to read after careful consideration. The class diagram involved is not completely displayed on the mobile phone, so you can switch to the computer version for reading.
ASP.NET WebForm, ASP.NET Mvc, ASP.NET WebApi and other Web frameworks are commonly used. Still relatively powerful, but with the development and iteration and the rise of the front end, some partners may feel outdated, because there are too many popular Web frameworks, of course, not limited to.net, a random number of others can be mentioned.
1.Java的Spring & Hibernate
2. The Python Django
3.Node Express and Koa
In fact, the most important thing is not how much is used, but how much is deposited. Although there may be outdated in the business field, there are still some things worth learning from the technical point of view, as I am doing. Net developed, so share your own learning. Net related Web framework.
Share what?
1. asp.net pipeline
ASP.NET pipeline front has a simple introduction, write when there may be some places did not consider the comprehensive follow-up time will be appropriate to modify, interested in can have a look, welcome to give feedback and discussion, so that each other better progress.
2.Web API route parsing
If only from ASP.NET WebAPI view may say relatively broad, last article only share ASP.NET pipeline model, later found too monotonous, more abstract, usually work also use less, not easy to understand, and then ready to share ASP.NET WebAPI this part together.
Asp.NET WebAPI is basically an extension of the Asp.NET pipeline, and of course WebAPI is divided into two parts
1.SelfHost: Self-host (an independent set of steps)
2.WebHost: ASP.NET pipeline
What SelfHost is, in fact, a self-host. It can host in Windows service, Winform program and console program, and does not rely on Asp.net pipeline. Those who have used WCF should know Point similar, do not do in-depth discussion and exploration.
Before sharing, I still need to outline what I’m going to share, because this way I can get a clear idea of what I’m going to share, and I can avoid getting sidetracked in the process
I’m going to use an abbreviation later to tell you what it is, for example WebAPI Mvc, because it’s a little bit tired to have all the upper and lower case……
1.[Web API Route Registration]
2.[Web API Routing]
3.[Web API pipeline assembly]
4.[Web API pipeline Extension]
How to share?
1. I will elaborate on WebAPI route registration and route processing by reading the source code and side instructions.
2. For pipeline assembly and extension although we will be exposed to it when reading the source code, I will still use Demo to illustrate it, because I think its design is really good, can not help but mention it separately, although I may be confused, BUT I still want to try it.
Share content
1. Web API routing Overview
An ASP.NET Web application has a global routing table represented by a Routes static attribute of type RouteCollection in a RouteTable class.
Why do you say that? Maybe it’s a little hard to understand, but let me give you a simple example
Public static void Register(HttpConfiguration config) {// Web API route //config.Routes.MapHttpRoute( // name: "DefaultApi", // routeTemplate: "api/{controller}/{Action}/{id}", // defaults: new { id = RouteParameter.Optional } //); Var ro = new {id = routeparameter. Optional}; / / get the default processor WebAPI IRouteHandler routeHandler = HttpControllerRouteHandler. Instance; RouteValueDictionary defaults = new RouteValueDictionary(ro); Route route = new Route("api/{controller}/{Action}/{id}", defaults, routeHandler); RouteTable.Routes.Add("DefaultApi", route); }Copy the code
It’s not just ASP.NET WebAPI that does this for routing tables. It also applies to ASP.NET WebForm and ASP.NET MVC It is also possible to add data directly to the network routing table at application startup, but this is just to confirm the above description. It is up to you whether you can use this in daily development.
Questions to ponder
1. Why is RouteCollection static? `
Because static objects remain in memory until the next collection from the program pool.
2. When we use WebAPI to develop application interface, have you ever thought about how our front-end Url request reaches our corresponding controller and Action?
In fact, it is controlled according to the road origin, as for how to control, how to achieve, I will slowly introduce later.
3. Since it is routing control, how to route?
First register the route and then bind it to the processor.
Then the user requests to match the corresponding processor according to the requested Url, and the processor parses the routing template rules.
Find Contrller and Action based on the parsed rules.
2. Register Web API routes
First of all, special routing does not share this time, and then have the opportunity to fill…
The simple representation is as follows, of course there are a lot of things in it, but it’s a little sketchy,
But all we developers who use frameworks see is a few simple lines of code, and unfortunately even that code is generated by the framework.
Registration way
1. We are in the web application starts up, first call GlobalConfiguration. Configure (WebApiConfig. Register) method, this method takes the argument is a Action < HttpConfiguration > as a parameter, Our first instinct when we see an Action is to execute it internally as a callback, but give us room to expand.
2. To framework definition WebApiConfig. Register method, there is no doubt that he has a HttpConfiguration type parameters, and the parameter is in the execution GlobalConfiguration. Configure internal incoming.
GlobalConfiguration
1. Open the GlobalConfiguration class to look at the above code. It is a static class. It contains three important static properties: Configuration, DefaultHandler, and DefaultServer. These three properties have been initialized when the static class is constructed Enjoy.
2. The first Configuration property is exactly what we need to perform the callback extension code above. This object has an HttpRouteCollection type Routes property, and the property has a MapHttpRoute extension method to add data to the routing table All we developers need to do is set up routing rules here.
3. Continuing to look at how a Configuration of type HttpConfiguration is initialized, we expand it and look at the code to see that it is created by an internal CreateConfiguration method. Creating it requires some additional types.
Registration process Steps
HttpConfiguration be structure needs to be some additional types is introduced to a HostedHttpRouteCollection object, internally it will incoming to like routes within the assigned to the attribute, For external use, and came to here in the Register method of user registration routing config. The Routes is a HostedHttpRouteCollection object.
2. We continue to see next MapHttpRoute routing extension mapping method, the mark of the above is an inherited from HttpRouteCollection HostedHttpRouteCollection, use it to call CreateRoute method returns a IHttp Examples of the Route.
3. Continue to turn to the interior of CreateRoute HostedHttpRouteCollection see it returns a HostedHttpRoute and it’s implementation IHttpRoute instance.
4. In HostedHttpRoute construction, there is an OriginalRoute property of type Route, which is assigned to the HttpWebRoute type inherited from (Route: RouteBase).
5. When the initial structure HttpWebRoute introduced into a routing template and a HttpControllerRouteHandler IRouteHandler type and a type of IHttpRoute HostedHttpRoute, then return, pay attention to the I RouteHandler can be understood as a handler for routing.
6. Return to the MapHttpRoute after corresponding IHttpRoute variables of type route is set to a HostedHttpRoute object, finally add the routing on the HostedHttpRouteCollection object template name and handler.
Registered so far in front of us the routing part has made a simple introduction, in the next section into the routing process, if you have any doubt welcome at any time in the process of reading and discussion, I strongly recommend reading this share after the establishment of a rough knowledge, have the time to be downloaded WebAPI source for reading, it will help better understanding.
3. Web API routing
In the previous section, we shared the process of routing registration in webAPI. We learned how to add a Route map to webAPI. Finally, a Route template and a Route handler form a Route object and then add it to the routing table.
Here we need to turn our attention to the ASP.NET pipe model, because the core of request processing is done by a guy in the ASP.NET pipe called UrlRoutingModule.
Yes, it is an HttpModule because it inherits from IHttpModule and implements the PostResolveRequestCache event that extends HttpApplication. Everything behind WebAPI is built around that extension event, as well as MVC The same goes for WebForm.
If you don’t know what classes and interfaces I highlight, you might want to read this share about the ASP.NET pipeline Model.
Equestcache event subscription for PostResolveRequestCache. The part of the routing process is all about the following code.
Process steps
A brief description:
-
Find the routing data RouteData based on the context when the request arrives.
-
Find the routing handler in RouteData IRouteHandler, and this IRouteHandler, it is in the previous section we registered in routing HttpControllerRouteHandler steps mentioned in step 6.
-
Assemble the RouteData and IRouteHandler together to form the RequestContext RequestContext.
-
GetHttpHandler in the routing handler finds a “request handler “IHttpHandler based on the incoming request context.
-
It turns out that the request handler, an HttpControllerHandler, takes over the rest of the operation, and from there it officially enters our WebAPI processing pipeline.
So far, assuming THAT I think you have a clear idea of the concepts and basic steps described above, let’s go inside the method and see how it works step by step.
Getting a routing object
1. Enter the GetRouteData method of the RouteCollection. The first iterator obtains the instance inherited from the RouteBase object.
2. Since current of type RouteBase is given when we register the route (step 5 of the route registration process), there is no doubt that current of type RouteBase gets an HttpWebRoute object, that is, returns RouteData data, and ultimately calls GetRout, the override method in HttpWebRoute EData, represented by a class diagram
classDiagram
RouteBase <|-- Route
Route <|-- HttpWebRoute
RouteBase: +GetRouteData()()
class Route{
+GetRouteData()
}
class HttpWebRoute{
+GetRouteData()
}
3. Since the HttpWebRoute attribute was constructed as HostedHttpRoute when the Route was registered, the GetRouteData method will call the GetRouteData() method at the tag
4. The method is simple, the current Route and register into the type of IRouteHandler HttpControllerRouteHandler processor assembly into a RouteData object returns.
To obtain an HttpHandler
1. The next is to obtain an HttpHandler a processor from the processor, we in the above said more than once, the routing handler is a type of IRouteHandler HttpControllerRouteHandler instance, then it is how to return to “the request processor”?
The HttpControllerHandler is created to signal that our HTTP request will be processed. It is simply an HttpHandler .
HttpControllerHandler perform
HttpControllerHandler takes routeData and handler, converts the routeData object to HostedHttpRouteData and converts the handler Is the HttpMessageInvoker object and then assigns to the internal private variable _server.
2. If this parameter of type HttpMessageHandler looks familiar, we saw it in the GlobalConfiguration class in step 3 of route registration.
classDiagram
class GlobalConfiguration{
+Configuration:HttpConfiguration
+DefaultHandler:HttpMessageHandler
+DefaultServer:HttpServer
}
3. Now may not be aware of its role, to continue to look down, will gradually clear, we know that an HttpHandler framework will be the default execution the ProcessRequest method, here is a Task of asynchronous method returns ProcessRequestAsync, in its internal call Process RequestAsyncCore
4. Note the await _server.sendAsync (request, cancellationToken) line marked above, where it receives a request context parameter and formally begins its execution.
5. See in step 1. This is a GlobalConfiguration $_server DefaultServer into the instance, we now need to go back to GlobalConfiguration officially see DefaultServer, for all these things with it Points.
private static Lazy<HttpServer> _defaultServer = CreateDefaultServer();
public static HttpServer DefaultServer
{
get { return _defaultServer.Value; }
}
private static Lazy<HttpServer> CreateDefaultServer()
{
return new Lazy<HttpServer>(() => new
HttpServer(_configuration.Value, _defaultHandler.Value));
}
Copy the code
DefaultServer is a attribute inherited from DelegatingHandler of type HttpServer, which is the header of our WebAPI pipe, HttpServer The SendAsync method is the first stop for all of our request processing, which also signals that the Http request has officially been taken over by the WebAPI pipeline and started processing.
4. Web API pipeline assembly
Before we learn about Web API pipeline assembly, we need to understand some basic class concepts and their relationships. Let’s take a quick look at the following class diagram to make it look familiar, because API pipeline consists of the following components.
classDiagram HttpMessageHandler <|-- DelegatingHandler HttpMessageHandler <|-- HttpRoutingDispatcher DelegatingHandler <|-- HttpServer HttpRoutingDispatcher <|-- HttpControllerDispatcher HttpMessageHandler : # SendAsync() class DelegatingHandler{ - innerHandler:HttpMessageHandler + innerHandler:HttpMessageHandler # SendAsync() } class HttpRoutingDispatcher{ # SendAsync() } class HttpServer{ Initialize() SendAsync() } class HttpControllerDispatcher{ # SendAsync() }
Of course, you might need some knowledge of design patterns, because it makes it easier for you to understand the design ideas. In the beginning of the introduction, I said THAT I was afraid to confuse myself, because it took me a long time to see it and understand it, and now I can only say that I try to share it.