ASP.NET5中间件

小的应用组件能够包含到Http请求管道当中,ASP.NET5 集成了中间件,被包在了应用程序的Configure方法当中。app

1. 什么是中间件async

中间件是一组被装到应用程序管道的请求和响应中的组件。每个组件能够选择地是否把当前的请求传到下一个组件当中,能够执行一些特定的动做在下一个组件以前或者以后执行。请求委托被用来建立这样的请求管道,用来处理你应用程序的请求。函数

请求的委托用IApplicationBuilder的run, map, use扩展方法来配置. 在Starup的configure里面能够作这样的配置,一个单独的请求委托能够指定一个匿名的方法,或者定义在一个可重复利用的类当中。这些可重复利用的类就是中间件,或者中间组件。每一个组件负责调用下一个组件,或者选择停止。性能

ASP.NET请求管道是由一系列的请求委托组成,一个一个地调用。以下图所示ui

每一个委托有机会执行相应的操做在下一个委托以前或以后。任何的委托能够选择中止传递请求到下一个委托。这就是所谓的请求短路,这有时候有好的,能够避免一些没必要要的工做,例如Authorization中间件在Authenticated以后调用以后的委托,当没有受权时会显示"Not Authorized", 异常处理能够捕获到,由于它在管道中早执行了。this

以下是应用程序的默认配置:spa

public void COnfigure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)设计

{orm

  ...中间件

  if(env.IsDevelopment())

  {

    app.UseBrowserLink();

    app.UseDeveloperExceptionPage();

    app.UseDatabaseErrorPage();  

  }

  else

  {

    app.UseExceptionHandler("/Home/Error");

  }

 

  app.UseStaticFiles();

  app.UseIdentity();

  app.UseMvc(routes => { routes.MapRout(name:"default", template:"{controller=Home}/{action=Index}/{id?}" });

}

UseExceptionHandler最早配置,这样它能够处理后续调用出现的任何异常,另外,这里的设计让请求的静态文件不须要用户的认证,这样能够提高性能,

切记:在应用配置时利用中间件的顺序是很重要的,确保你的应用程序适合你的应用场景。

一个简单的匿名的调用以下:

app.Run(async context => { await context.Response.WriteAsync("Hello, World!"); });

注意,执行完上面的这条语句,就会停止执行下面的任何语句。

再看一个例子, 在委托的参数里能够增长一个next参数,来调用下一个委托。

public void ConfigureLogInline(IApplicationBuilder app, ILoggerFactory loggerfactory)

{

  loggerfactory.AddConsole(minLevel: logLevel.Information);

  var logger = loggerfactory.CreateLogger(_environment);

  app.Use(async (context, next) => {logger.LogInfromation();

  await next.Invoke();

  logger.LogInformation("Finished handling request".);});

  app.Run(async context=>{ await context.Response.WriteAsync("Hello from" + _environment); });

}

注意:不在要调用next以后再修改HttpResponse, 由于后续的委托也会写,致使错乱。

2 Run, Map, and Use

通常地, 咱们用run的时候,是不会调用其它的组件的,也就是不会再调next的请求委托。因此,Run只能在最后被调用。

下面两个结果是同样的

public void COnfigureEnvironmentOne(IApplicationBuilder app)

{

  app.Run(async context => { await context.Response.WriteAsync("Hello from " + _environment);

}

public void ConfigureEnvironmentTwo(IApplicationBuilder app)

{

  app.Use(next => async context =>{ await context.Response.WriteAsync("Hello from " + _environment);

}

Map*扩展用来分支管道,下面会演示一个基于请求路径的分支,Map扩展用来把请求的路径和处理的方法作一个映射,例子以下:

private static void HandleMapTest(IApplicationBuilder app)

{

  app.Run(async context => { await context.Response.WriteAsync("Map Test Successful"); });

}

public void ConfigureMapping(IApplicationBuilder app)

{

  app.Map("/maptest", HandleMapTest);

}

MapWhen方法能够支持谓词的中间分支, 例如:

public void COnfigureMapWhen(IApplicationBuilder app)

{

  app.MapWhen(context => { return context.Request.Query.ContainsKey("branch"); }, HandleBranch);

  app.Run(async context => { awat context.Response.WriteAsync("Hello from " + _environment); });

}

private static void HandleBranch(IApplicationBuilder app)

{

  app.Run(async context => { await context.Response.WriteAsync("Branch used."); });

}

上面的例子任何的请求参数中含有branch的都走HandleBranch分支,其它走下面的。

3. 内建的中间件

中间件      描述

Authentication  提供认证支持

CORS      配置跨源资源共享

Diagnostics   包含错误页的支持和运行时的信息

Routing      定义限制请求的路由

Session       提供管理用户会话的支持

Static Files       提供静态文件,文件夹的浏览

4. 编写中间件

对于复杂的请求处理,ASP.NET团队建议实现本身的中间件,在Configure里去调用,例如:

public class RequestLoggerMiddleware

{

  private readonly RequestDelegate _next;

  private readonly ILogger _logger;

  public RequestLoggerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)

  {

    _next = next;

    _logger = logggerFactory.CreateLogger<RequestLoggerMiddleware>();

  }

 

  public async Task Invoke(HttpContext context)

  {

    _logger.LogInformation("Handling request: " + context.Request.Path);

    await _next.Invoke(context);

    _logger.LogInformation("Finished handling request.");

  }

}

public static class RequestLoggerExtensions

{

  public static IApplicationBuilder UseRequestLogger(this IApplicationBuilder builder)

  {

    return builder.UseMiddleware<RequestLoggerMiddleware>();

  }

}

在Configure方法中你能够简单地利用一行代码就搞定了。

app.UseRequestLogger();

在UseMiddleware<T>方法中ReuqestLoggerMiddleware的构造函数里的参数会被DI自动地注入进去。

相关文章
相关标签/搜索