Host and boot

Application startup process

Pay attention to the point

  • Load application configuration from appSettings. josn, AppSettings. {Environment}. Json, user Secrets (development Environment only), Environment variables, and command-line arguments.
  • Load configuration items from an environment variable starting with ASPNETCORE_, such as ASPNETCORE_ENVIRONMENT, and from a command line argument.
  • Three environment names
    • -Leonard: Development.
    • Staging: a rehearsal.
    • Production.

Startup class

Provide the application with classes for configuration startup. Two important methods are the ConfigureServices method and Configure method,

At startup, the ConfigureServices method is executed multiple times to add services to the container, while the Configure method is invoked only once.

ConfigureServices

Add services to the container.

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Copy the code

Configure

Add middleware to the request pipeline.

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  if (env.IsDevelopment())
  {
    app.UseDeveloperExceptionPage();
  }
  else
  {
    app.UseHsts();
  }

  // Add middleware
  app.Run(async (context) =>
          {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("-- -- -- -- -- -- -- -- -- -- -");
            stringBuilder.AppendLine($"Host: { context.Request.Host}");
            stringBuilder.AppendLine($"Method: { context.Request.Method}");
            stringBuilder.AppendLine($"Path: {context.Request.Path}");
            stringBuilder.AppendLine($"Protocol: {context.Request.Protocol}");
            foreach(var item in context.Request.Headers)
            {
              stringBuilder.AppendLine("-- -- -- -- -- -");
              stringBuilder.AppendLine($"{item.Key} : {item.Value}");
            }

            await context.Response.WriteAsync(stringBuilder.ToString());
          });

  app.UseHttpsRedirection();
  app.UseMvc();
}
Copy the code

The middleware

ASP.NET Core has several built-in middleware, including MVC, authentication, error, static files, HTTPS redirection and cross-origin Resource Sharing (CORS), etc. ASP.NET Core also allows you to add custom middleware to the pipeline.

Adding Middleware

There are two main methods, Use and Run, which receive the following parameters:

  • Run method
public delegate Task RequestDelegate(HttpContext context);
Copy the code
  • Use Method parameter type
Func<HttpContext, Func<Task>, Task>
Copy the code

Example: Add middleware using the run method

In the Configure method of the Startup class, note the order in which the middleware is added. The configuration of the middleware is the order in which the request pipeline is executed

app.Run(async (context) =>
{
  StringBuilder stringBuilder = new StringBuilder();
  stringBuilder.AppendLine("-- -- -- -- -- -- -- -- -- -- -");
  stringBuilder.AppendLine($"Host: { context.Request.Host}");
  stringBuilder.AppendLine($"Method: { context.Request.Method}");
  stringBuilder.AppendLine($"Path: {context.Request.Path}");
  stringBuilder.AppendLine($"Protocol: {context.Request.Protocol}");
  foreach(var item in context.Request.Headers)
  {
    stringBuilder.AppendLine("-- -- -- -- -- -");
    stringBuilder.AppendLine($"{item.Key} : {item.Value}");
  }

  await context.Response.WriteAsync(stringBuilder.ToString());
});
Copy the code

The output from Postman is:

Other usage methods

The Map method

Map decides whether to proceed with subsequent middleware execution on a new branch based on whether the specified request path is matched, and does not return to the original pipe after execution on the new branch.

MapWhen method

MapWhen can satisfy more complex conditions. It accepts Func<HttpContext, bool> and uses this parameter as its criterion. Therefore, it makes a more detailed determination of the HttpContext object (such as whether it contains the specified request message, etc.). It then decides whether to proceed to the new branch to continue executing the specified middleware.

UseWhen method

UseWhen and MapWhen take exactly the same parameters, but unlike Map and MapWhen, the branch created by UseWhen continues back to the original pipe after execution.

Custom middleware

The constructor

The constructor should contain a parameter of type RequestDelegate that represents the next middleware to be called in the pipe.

private readonly RequestDelegate _next;
public MyMiddleWare(RequestDelegate requestDelegate,IHostingEnvironment environment)
{
  this._next = requestDelegate;
}
Copy the code

Invoke method

The Invoke method requires that the return value be of type Task. And since it contains an argument of type HttpContext to handle the request.

In the Invoke method, the HTTP request method is judged, and if the condition is met, the next middleware is executed. Otherwise, a 400 Bad Request error is returned and a custom header is added to the response to explain the cause of the error.

public Task Invoke(HttpContext context)
{
  var requestMethod = context.Request.Method.ToUpper();
  if(requestMethod == HttpMethod.Get || 
    request.Method == HttpMethod.Head)
  {
  	return _next(context);
  }else
  {
  	context.Response.StatusCode = 400;
    context.Response.Headers.Add("X-AllowHTTPVerb".new[] {"GET"."HEAD"});
    context.Response.WriteAsync(To support Get, Head methods);
    returnTask.CompletedTask; }}Copy the code

Add custom middleware

  • Use generic

Add middleware to the Configure method of the Startup class:

app.UseMiddleware<MyMiddleWare>();
Copy the code
  • Using extension methods

    • Define extension methods
    public static class MyMiddleWareExtensions
    {
    	public static IApplicationBuilder UseMyMiddleWare(this IApplicationBuilder builder)
        {
      		returnbuilder.UseMiddleware<MyMiddleWare>(); }}Copy the code
    • Add middleware to the configuration
    app.UseMyMiddleWare();
    Copy the code

Complete sample code

Middleware class MyMiddleWare:

public class MyMiddleWare
{
  // constructor, notice that the next middleware is called
  private readonly RequestDelegate _next;
  public MyMiddleWare(RequestDelegate requestDelegate,IHostingEnvironment environment)
  {
    this._next = requestDelegate;
  }
  // The Invoke method, noting the parameter and return value types
  public Task Invoke(HttpContext context)
  {
    var requestMethod = context.Request.Method.ToUpper();
    if(requestMethod == HttpMethod.Get || 
      request.Method == HttpMethod.Head)
    {
      return _next(context);
    }else
    {
      context.Response.StatusCode = 400;
      context.Response.Headers.Add("X-AllowHTTPVerb".new[] {"GET"."HEAD"});
      context.Response.WriteAsync(To support Get, Head methods);
      returnTask.CompletedTask; }}}Copy the code

MyMiddleWareExtensions class:

public static class MyMiddleWareExtensions
{
	public static IApplicationBuilder UseMyMiddleWare(this IApplicationBuilder builder)
    {
  		returnbuilder.UseMiddleware<MyMiddleWare>(); }}Copy the code

Startup:

app.UseMyMiddleWare();
Copy the code