In the 1th chapter of project structure analysis, we mentioned that Startup.cs
as the entry point for the entire program, it is equivalent to the traditional Global.asax
file, that is, to initialize the system-level information (for example, the routing configuration in MVC). In this chapter we will analyze how to initialize these system-level information here.
Pipeline differences between old and new versions
The biggest difference between the ASP.net 5 and previous versions is a new rewrite of the HTTP pipeline, in which the request filter is typically HttpModule
used for module components, which HttpApplication
respond to events within the defined cycle, to implement authentication, global error handling , log and other functions. The traditional form form authentication is one HTTPModule
. HTTPModule
not only can Request
you filter the request, it can also interact with the Response
response and modify it. These HttpModule components inherit from the IHttpModule interface, which is located System.Web.dll
in.
HttpModule code can be added not only in each event cycle in Global.asax, but also as a separate class library and registered in Web.config.
The new version of ASP.net 5 abandons the heavyweight System.Web.dll, and accordingly introduces Middleware
the concept of the Middleware
official definition as follows:
Pass through components this form a pipeline between a server and application to inspect, route, or modify request and res Ponse messages for a specific purpose.
Between the pipeline pipeline between the server and the application, inserting multiple middleware components for a specific purpose to check the request and response responses
Check, route, or modify.
The definition and the traditional HttpModule
as well HttpHandler
as the special image.
Registration and configuration of middleware
In Asp.net5, the request requests pipeline (Pipeline) is accessed in the Startup class, which is a contract class, and the ConfigureServices
methods, Configure
methods, and corresponding parameters are agreed in advance, so no changes can be made.
Dependency processing in Middleware: Configureservices method
Dependency injection is used in the various default middleware in Asp.net5, so when using the functionality in middleware, it is necessary to register the types and mapping relationships required for dependency injection into the dependency injection management system, that is, the Iservicecollection collection, while con The Figureservices method receives a iservicecollection type argument, which is a collection of all registered types. Managed through a native dependency injection component (for dependency injection in Asp.net5, we'll explain it in a separate section), in which we can add new types and type mapping relationships to the collection, examples are as follows:
ADD MVC Services to the Services container.
Services. Addmvc ();
The code in the example is used to add the service type associated with the MVC module to the system to support the MVC feature, which is an extension method for adding multiple types associated with MVC in the collection.
Registration and configuration of middleware: Configure method
The signature of the Configure method is as follows:
public void Configure (Iapplicationbuilder app, Ihostingenvironment env, iloggerfactory loggerfactory)
{
//...
}
Configure
The method receives three parameters: the IApplicationBuilder
parameter of the type is used to build the configuration information for the entire application, and IHostingEnvironment
the parameters of the class are env
used to access the content of the system environment variable, and the ILoggerFactory
type of loggerfactory
content processing for the log, which IApplicationBuilder
The parameters of a type are most important, and the parameter instance has a series of extension methods for registering various middleware into the request pipeline (Pipeline). The main difference between this approach and the HTTP pipeline in the previous asp.net is that the composite model in the new version replaces the event model in the old version. This also requires that in the new ASP.net, the order of the middleware component registration is important because the latter component may have to be used to the previous component, so it must be registered in the order of dependency, for example, the template code example for the current MVC project is as follows:
Add static files to the request pipeline.
App. Usestaticfiles ();
ADD cookie-based authentication to the request pipeline.
App. Useidentity ();
ADD MVC to the request pipeline.
App. USEMVC (Routes =>{/*...*/});
In the example, the extension method, which is all in the extension method, UseStaticFiles
UseIdentity
UseMvc
IApplicationBuilder
will register the new middleware by calling the extension method app.UseMiddleware
method and eventually calling the method, app.Use
which is defined as follows:
Public interface Iapplicationbuilder
{
//...
Iapplicationbuilder use (func<requestdelegate, requestdelegate> middleware);
}
By code, you can see that middleware is Func<RequestDelegate, RequestDelegate>
an instance of the Func that receives a RequestDelegate
parameter and returns a RequestDelegate
type of value. RequestDelegate
The source code is as follows:
Public delegate Task Requestdelegate (HttpContext context);
By source, we can see that it RequestDelegate
is a delegate function that receives an instance of the HttpContext
type and returns an Task
asynchronous object of the type. That RequestDelegate
is, a function that can return a RequestDelegate
function of its own type, The entire asp.net is the construction of the pipeline (Pipelien) in this way, where each middleware is chained to the next middleware, and the object can be modified or maintained throughout the process, HttpConext
of course, HttpContext
Includes the common HttpRequest
and instance objects that we normally manipulate HttpResponse
.
Note: HttpContext
, HttpRequest
HttpResponse
in asp.net 5, are new types that are redefined.
Definition of middleware
Since every middleare is Func<RequestDelegate, RequestDelegate>
an instance, is that not middleware definition to satisfy a rule? Is it inherited from an abstract base class or is it an excuse? By looking up the relevant code, we see that the middleware is defined on the basis of the contract, the specific rules are as follows:
The first parameter of the constructor must be the next processing function in the pipeline, that is, the requestdelegate; You must have an Invoke function, accept the context parameter (that is, httpcontent), and then return to the Task;
Examples are as follows:
public class Middlewarename
{
requestdelegate _next;
Public Middlewarename (requestdelegate next)
{
_next = next;//Receive incoming requestdelegate instance
} public
Async Task Invoke (HttpContext context)
{
//process code, such as processing context. The content in the request is
Console.WriteLine ("Middleware starts processing");
Await _next (context);
Console.WriteLine ("Middleware End Processing");
Process code, such as handling the context. Content in response
}
}
The template code can be seen, first of all, a middleware constructor to receive a Requestdelegate instance, first save in a private variable, and then by calling Invoke
the method (and receiving HttpContent
the instance) and return a Task
, And in the calling Invoke
method, to pass the await _next(context);
statement, chained to the next middleware, our processing code is mainly in the chain statement before and after the execution of the relevant code.
For example, if we want to record the execution time of the page, first, we first define a timerecordermiddleware, the code is as follows:
public class Timerecordermiddleware
{
requestdelegate _next;
Public Timerecordermiddleware (requestdelegate next)
{
_next = next;
}
Public Async Task Invoke (HttpContext context)
{
var sw = new Stopwatch ();
Sw. Start ();
Await _next (context);
var newdiv = @ "<div id=" "Process" > page processing time: {0} ms </div></body>;
var text = string. Format (Newdiv, SW. Elapsedmilliseconds);
Await context. Response.writeasync (text);
}
There are many ways to register a middleware, as follows is an instance-type registration code:
App. Use (Next => new Timerecordermiddleware (next). Invoke);
Alternatively, you can use the Usemiddleware extension method for registration, as shown in the following example:
App. Usemiddleware<timerecordermiddleware> ();
App. Usemiddleware (typeof (Timerecordermiddleware)); Both ways can be
Of course, you can also define an extension method of your own to register the middleware code as follows:
public static Iapplicationbuilder Usetimerecordermiddleware (this iapplicationbuilder app)
{return
app. Usemiddleware<timerecordermiddleware> ();
}
Finally, in the Configure method of the startup class to register, the code is as follows:
public void Configure (Iapplicationbuilder app, Ihostingenvironment env, iloggerfactory loggerfactory)
{
app. Usetimerecordermiddleware (); To put it in front for statistics, if you put it behind MVC, you can't count the time.
//etc.
}
Compile, restart, and access the page, at the bottom of the page you can see the content of the page's running time.
Use of common middleware functions
App. Useerrorpage ()
In the case of ihostingenvironment.environmentname as development, the error message is displayed, and the type of display of the error message can be set by the additional errorpageoptions parameters, you can set up all the display, or you can set only show co One or more of the Okies, Environment, Exceptiondetails, Headers, Query, SourceCode sourcecodelinecount.
App. Useerrorhandler ("/home/error")
Captures all program exception errors and jumps the request to the specified page for the purpose of friendly hints.
App. Usestaticfiles ()
Opening a static file can also take the function of the pipeline pipeline processing process.
App. Useidentity ()
Turn on the ASP.net identity authentication feature based on cookies to support pipeline request processing.
To define middleware functions directly using delegates
Since middleware is an Func<RequestDelegate, RequestDelegate>
instance of a delegate type, we can also do without having to define a separate class, in the Startup
class, by using the delegate invocation, as the following example:
public void Configure (Iapplicationbuilder app, Ihostingenvironment env, iloggerfactory loggerfactory)
{
app. Use (New Func<requestdelegate, requestdelegate> (next => content => Invoke (next, content));
Other
}
//Note the parameters of the Invoke method
private Async Task Invoke (requestdelegate Next, HttpContext content)
{
Console.WriteLine ("Initialize component Start");
Await next. Invoke (content);
Console.WriteLine ("Pipe Next Step execution Complete");
}
Make a simple middleware base class
Although there are agreed methods, but sometimes we are in the development of the time will be confused, can not remember what kind of agreement, so, here we could define an abstract base class, and then all the middleware at the time of definition will inherit the abstract class and overload Invoke method, So as to avoid the problem of the agreed to forget. The code is as follows:
<summary>
///Abstract base class
///</summary> public
abstract class Abstractmiddleware
{
Protected requestdelegate Next {get; set;}
Protected Abstractmiddleware (requestdelegate next)
{this
. Next = next;
}
Public abstract Task Invoke (HttpContext context);
}
<summary>
///Example middleware
///</summary> public
class Demomiddleware: Abstractmiddleware
{public
demomiddleware (requestdelegate Next): Base (Next)
{
}
Public Async override Task Invoke (HttpContext context)
{
Console.WriteLine ("Demomiddleware Start.");
Await Next.invoke (context);
Console.WriteLine ("Demomiddleware end.");
}
Use the same method as above.
Terminates a chained call or blocks all middleware
In some cases, of course, according to certain conditions after the judgement, may not need to continue to go on, but to think of a confidant to return the results, then you can ignore the call in your middleware await next.Invoke(content);
, direct use · The Response.writeasync method outputs the content.
In addition, in some cases, you might want to implement the functionality of the handler in the previous release, that is, not often any pipeline directly respond to response, The new ASP.net provides a run method to implement this feature, and you can achieve similar content output by invoking the following code in the Configure method.
App. Run (Async context =>
{context)
. Response.ContentType = "text/html";
Await context. Response.writeasync ("Hello world!");
For information on asp.net 5 runtime, please visit: https://msdn.microsoft.com/en-us/magazine/dn913182.aspx
Legacy issues
In an MVC project, all dependency injection types are obtained by IServiceProvider instances, which can now be obtained in the following form:
var services = context.requestservices;
var services = app in Controller. ApplicationServices; Startup in
After you get the instance, you can get an object of a type by using the following methods:
var controller = (AccountController) services. GetService (typeof (AccountController));
To determine if the object being fetched is null
If you refer to the Microsoft.Framework.DependencyInjection namespace, you can also use the following three extension methods:
var controller2 = (AccountController) services. Getservice<accountcontroller> ();
To determine if the object being fetched is null
//Two, and if the AccountController instance obtained is null, the field throws an exception instead of returning the null
var Controller3 = ( AccountController) Services. Getrequiredservice (typeof (AccountController));
var controller4 = (AccountController) services. Getrequiredservice<accountcontroller> ();
So, what's the problem? How can I get to HttpContext and Iapplicationbuilder instances in startup and controller to use these dependency injection services?
How do I get a iapplicationbuilder instance?
Answer: In the startup, the Iapplicationbuilder instance is saved in a single case variable, and the whole station can be used later.
How do I get a HttpContext instance?
Answer: Reference dependency injection for the general class of the injection section
Reference: Http://www.mikesdotnetting.com/article/269/asp-net-5-middleware-or-where-has-my-httpmodule-gone