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自動地注入進去。

相關文章
相關標籤/搜索