使用 ASP.NET Core 1.1
ASP.NET Core middleware 方法被定義在
Startup
類別的Configure
方法裡,當應用程式啟動的時候,框架會自動執行這個方法,並提供IApplicationBuilder
實例,使用該實例的Use
方法註冊自定義 middlewareIApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
Use
方法接受一個Func參數,該參數接受和返回都是 RequestDelegate
public delegate Task RequestDelegate(HttpContext context)[範例 1]:
app.Use(next => { return async context => { await context.Response.WriteAsync("Hello World!"); await next(context); }; });用 lambda 表示 Func<RequestDelegate, RequestDelegate>,參數 next 是下一個middle;return的是一個新的 RequestDelegate,他接收 HttpContext 實例
除了[範例 1]以外,同個命名空間(Microsoft.AspNetCore.Builder)下有一個擴展方法寫法較為簡短
[範例 2]:
他接收的參數類型:[範例 2]:
app.Use(async (ctx, next) => { await ctx.Response.WriteAsync("Hello World!"); await next(); });
Func<HttpContext, Func<Task>, Task>如果是最後一個middleware, 可以使用 Run(就像Use沒用next)
app.Run(async context => await context.Response.WriteAsync("Hi"));
另一個建立middleware的方式允許在class裡封裝邏輯,該class必須有接受HttpContext的Invoke方法:
public class MyMiddleware { private readonly RequestDelegate _next; public MyMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { await context.Response.WriteAsync("Hi!"); await _next(context); } }該方法必須有一個接受RequestDelegate實例的建構式,可以在Invoke方法裡去呼叫下一個middleware。
使用自定義middleware的方式:
app.UseMiddleware<MyMiddleware>();或是擴展
public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder app) { app.UseMiddleware<MyMiddleware>(); return app; }然後使用他
app.UseMyMiddleware();
如果middleware需要呼叫另一個物件的方法,可以在middleware裡面建立物件,更優雅的寫法是使用內建的dependency injection
Startup
類別的ConfigureServices
方法可以註冊依賴物件,該方法比Configure早執行,所以所有的依賴物件可以被middleware使用建立interface和class:
public interface IGreeter { string Greet(); } public class Greeter : IGreeter { public string Greet() { return "Hi by Greeter!"; } }在ConfigureServices方法裡面註冊:
services.AddTransient<IGreeter, Greeter>();AddTransient方法在每次request時都會建立一個實例,其他還有AddSingleton/AddScoped或是簡單的Add,整個DI系統的描述在docs.asp.net/dependency-injection
完成註冊後,直接在 Configure 方法使用:
app.Use(async (context, next) => { IGreeter greeter = context.RequestServices.GetService<IGreeter>(); await context.Response.WriteAsync(greeter.Greet()); await next(); });或是寫在自定義middleware:
public class MyMiddleware { private readonly RequestDelegate _next; private readonly IGreeter _greeter; public MyMiddleware(RequestDelegate next, IGreeter greeter) { _next = next; _greeter = greeter; } public async Task Invoke(HttpContext context) { await context.Response.WriteAsync(_greeter.Greet()); await _next(context); } }如果DI系統知道這些參數的類型,則在 class 被實例化時,它們將被自動解析