ASP. NET Core Learning Summary (1)

Source: Internet
Author: User
Tags httpcontext

After so long time of study, finally want to give oneself this time of study work to make a summary. I remember when I first started studying, nothing was available and the light chewed the document. Fortunately, however, there are some basics of web development. At least ASP. WebForm and MVC have some knowledge, though not very proficient. Speaking of which, the overall process of the entire Web application and what HTTP protocol are not well understood. After all, under the protection of Microsoft's father's hard growth.

1. Concept

The concept of this kind of thing, the feeling is too academic. That is, the time is long, slowly can understand some of the words used frequently. For most people, we surf the web almost every day. Perhaps our basic understanding of Web applications begins here. Unfortunately, many people still stay in the open browser to see the Web page. So that, for the page is how to come, how to present the concept of No.

A network application is a distributed system, usually composed of a client and a server. Communication through the HTTP protocol is a request/response mode. Browsers typically serve as clients, and we develop Web applications that are typically served as a server.

2. Principle

The above image is from Microsoft's official documentation, which simply and intuitively describes the fundamentals of the Web application we will be developing. First, the ASP. NET Core application represents our entire Web application, which communicates externally with the HTTP protocol. Within our program, the first is the framework of the ASP. Kestrel is an underlying service that can listen to and respond to requests, and it encapsulates the received HTTP message into the application code HttpContext passed to us. At the same time, the application-processed response is converted to a response message back to the client.

? Now, let's go deep inside the application code. An application pipeline is essentially composed of a chain of delegates. The delegate named Requestdelegate has two parameters, the first is HttpContext, the second is next, and the type is requestdeletage, which points to the next delegate.

  

We see that requests and responses are essentially handled by a series of middleware processes. In fact, these middleware will eventually be compiled into a chain of delegates (all middleware classes should include an Invoke method and a constructor as agreed, and the constructor contains the HttpContext in the Next,invoke). In summary, when a request comes in, the first delegate is executed first. The interior of the first delegate can choose whether to invoke the next delegate. As shown, if the first middleware essentially becomes a delegate, do not call next (). Then, the request is shorted in the middleware, where the request is no longer passed down, and the response is returned directly.

Next, let's introduce the core part of the ASP. For each request, there should be a corresponding URL. And our program will usually have a corresponding processing method, that is, our controller action. The first problem that the framework solves now is how to map to the corresponding processing method, which is the routing mechanism, based on the URL.

The routing mechanism is implemented by Microsoft.AspNetCore.Routing. The most central part of it is the code in Routermiddleware.

         Public AsyncTask Invoke (HttpContext HttpContext) {varContext =NewRoutecontext (HttpContext); Context. ROUTEDATA.ROUTERS.ADD (_router);//_router is obtained from the service container through dependency injection .//This step is the most important, it will be based on Routecontext to find a suitable handler//In other words, the entire route match is how this step is implemented            await_router.            Routeasync (context); if(Context. Handler = =NULL) {_logger.                Requestdidnotmatchroutes (); await_next.            Invoke (HttpContext); }            Else{httpcontext.features[typeof(Iroutingfeature)] =Newroutingfeature () {Routedata=context.                Routedata,}; awaitcontext. Handler (context.            HttpContext); }        }

The above _router is a variable of the Irouter interface type. Essentially, the implementation class was added when we registered the MVC service. As shown below:

            //            // Route handlers             //            // Only one per app            // many per app
            var New Routebuilder (APP)            {                = app. Applicationservices.getrequiredservice<mvcroutehandler>(),            };            Configureroutes (routes);            Routes. Routes.insert (0, Attributerouting.createattributemegaroute (app. ApplicationServices));             return app. Userouter (routes. Build ());

We say that both Mvcroutehandler and Mvcattributeroutehandler implement the Irouter interface. The first part of the code is intended to add these two handler to the service container. The second part of the code is intended to be removed from the service container and passed to the routing middleware.

? So, the question is, how are Mvcroutehandler and Mvcattributeroutehandler implemented? First, let's take a look at how Mvcroutehandler is implemented internally.

 PublicTask Routeasync (Routecontext context) {if(Context = =NULL)            {                Throw NewArgumentNullException (nameof (context)); }              //Audition            varCandidates =_actionselector.selectcandidates (context); if(Candidates = =NULL|| Candidates. Count = =0) {_logger. Noactionsmatched (context.                Routedata.values); returnTask.completedtask; }                          //Featured            varActiondescriptor =_actionselector.selectbestcandidate (context, candidates); if(Actiondescriptor = =NULL) {_logger. Noactionsmatched (context.                Routedata.values); returnTask.completedtask; }              //compiling into requestdelegate using lambda expressionsContext. Handler = (c) = =            {                varRoutedata =C.getroutedata (); varActioncontext =NewActioncontext (context.                HttpContext, Routedata, Actiondescriptor); if(_actioncontextaccessor! =NULL) {_actioncontextaccessor.actioncontext=Actioncontext; }                varInvoker =_actioninvokerfactory.createinvoker (Actioncontext); if(Invoker = =NULL)                {                    Throw NewInvalidOperationException (Resources.formatactioninvokerfactory_couldnotcreateinvoker (                Actiondescriptor.displayname)); }                  //This is the core processing part .                returnInvoker.            InvokeAsync ();            }; returnTask.completedtask; }

Let us explain that the key is _actionselector. It will pick out candidates (candidate) according to Routecontext, which is the first step. This step only filters out all of the URL-matching actions, and the second step needs to continue to consider the issue of routing constraints. If there are more than one qualifying action in the second step, an exception is thrown. In the third step we see the use of a lambda expression to generate a requestdelegate delegate, a handler (previously seen in the routing middleware). What we need to focus on in this delegate is Invoker, which is a variable of type Iactioninvoker. Its default implementation is usually Controlleractioninvoker, and we'll delve into the internal implementation of this class later. We see that invoker is generated by the factory function according to Actioncontext, and finally calls the InvokeAsync method. That is, we still have no way of knowing how the action code we write is executed. And to know this, we can only go further.

We see that invoker is _actionInvokerFactory created by. _actionInvokerFactory This is the iactioninvokerfactory type, which is obtained from the service container. Let's find out how it was injected into the container.

            //            // Action Invoker             //            // The iactioninvokerfactory is cachable            Services. Tryaddsingleton<iactioninvokerfactory, actioninvokerfactory>();            Services. Tryaddenumerable (                servicedescriptor.transient<iactioninvokerprovider, Controlleractioninvokerprovider> ());

As you can see, it injects a default implementation, Actioninvokerfactory. The interior of it is this:

  Publiciactioninvoker Createinvoker (Actioncontext actioncontext) {varContext =NewActioninvokerprovidercontext (Actioncontext); foreach(varProviderinch_actioninvokerproviders) {provider.            Onprovidersexecuting (context); }             for(vari = _actioninvokerproviders.length-1; I >=0; i--) {_actioninvokerproviders[i].            onprovidersexecuted (context); }            returncontext.        Result; }

In fact, Actioninvokerfactory did not deal with it directly, but instead gave it to Iactioninokerprovider. And in the above we see that its default implementation is Controlleractioninvokerprovider.

 Public voidonprovidersexecuting (Actioninvokerprovidercontext context) {if(Context = =NULL)            {                Throw NewArgumentNullException (nameof (context)); }            if(Context. Actioncontext.actiondescriptor iscontrolleractiondescriptor) {                varControllerContext =NewControllerContext (context.                Actioncontext); //Perf:these is rarely going to being changed, so let's go copy-on-write.Controllercontext.valueproviderfactories =NewCopyonwritelist<ivalueproviderfactory>(_valueproviderfactories); ControllerContext.ModelState.MaxAllowedErrors=_maxmodelvalidationerrors; //Caching Policies                varCacheresult =_controlleractioninvokercache.getcachedresult (ControllerContext); varInvoker =NewControlleractioninvoker (_logger, _diagnosticsource, control                Lercontext, Cacheresult.cacheentry, cacheresult.filters); Context. Result=Invoker; }        }

We finally found out that Invoker came from here, and that it did a caching strategy. Now, it is time to uncover the controlleractioninvoker of this mystery.

ASP. NET Core Learning Summary (1)

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.