問(wèn)題
如何創(chuàng)建一個(gè)最簡(jiǎn)單的ASP.NET Core中間件?
答案
使用VS創(chuàng)建一個(gè)ASP.NET Core 2.0的空項(xiàng)目,注意Startup.cs中的Configure()方法:
1
2
3
4
5
6
7
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.Run(async (context) => { await context.Response.WriteAsync( "Hello World! (Run)" ); }); } |
比較好的創(chuàng)建請(qǐng)求管道的方法是使用IApplicationBuilder上的擴(kuò)展方法:
1
2
3
4
5
6
7
|
public static void RunHelloWorld( this IApplicationBuilder app) { app.Run(async (context) => { await context.Response.WriteAsync( "Hello World! (Run)" ); }); } |
1
2
3
4
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.RunHelloWorld(); } |
運(yùn)行,此時(shí)頁(yè)面顯示:
上面我們使用IApplicationBuilder.Run()來(lái)配置中間件,另外一種方法是IApplicationBuilder.Use():
1
2
3
4
5
6
7
8
|
public static void UseHelloWorld( this IApplicationBuilder app) { app.Use(async (context, next) => { await context.Response.WriteAsync( "Hello World! (Use)\n" ); await next(); }); } |
1
2
3
4
5
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHelloWorld(); app.RunHelloWorld(); } |
運(yùn)行,此時(shí)頁(yè)面顯示:
將中間件作為單獨(dú)的類定義是更好的實(shí)踐方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class HelloWorldMiddleware { private readonly RequestDelegate _next; public HelloWorldMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { await context.Response.WriteAsync( "Hello World! (Use in Class)\n" ); await _next(context); } } public static class UseHelloWorldInClassExtensions { public static IApplicationBuilder UseHelloWorldInClass( this IApplicationBuilder app) { return app.UseMiddleware<HelloWorldMiddleware>(); } } |
1
2
3
4
5
6
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHelloWorld(); app.UseHelloWorldInClass(); app.RunHelloWorld(); } |
運(yùn)行,此時(shí)頁(yè)面顯示:
討論
中間件是一個(gè)攔截HTTP請(qǐng)求和響應(yīng)消息的組件。我們通過(guò)創(chuàng)建這些組件鏈,來(lái)為我們的應(yīng)用程序創(chuàng)建一個(gè)請(qǐng)求管道。
我們通過(guò)Configure()方法的IApplicationBuilder參數(shù)來(lái)創(chuàng)建這個(gè)請(qǐng)求管道,IApplicationBuilder參數(shù)有如下方法:
- Run():添加中間件并終止請(qǐng)求管道(也就是說(shuō)不再調(diào)用下一個(gè)中間件)。
- Use():添加中間件,使用lambda表達(dá)式或者一個(gè)具體的類。
- Map():根據(jù)請(qǐng)求路徑添加中間件。
Run
這個(gè)方法接受RequestDelegate委托作為參數(shù),當(dāng)委托方法被調(diào)用時(shí)接受HttpContext參數(shù)。這個(gè)委托方法返回void,因?yàn)樗鼤?huì)終止請(qǐng)求管道。
Use
這個(gè)方法接受Func委托作為參數(shù),此委托方法有兩個(gè)參數(shù),分別是HttpContext和指向下一個(gè)中間件的next,返回空(Task)。如果沒(méi)有調(diào)用下一個(gè)中間件,就會(huì)終止請(qǐng)求管道(和Run效果一樣)。
UserMiddleware
當(dāng)通過(guò)單獨(dú)類創(chuàng)建中間件時(shí),我們使用UseMiddleware方法,并將具體的實(shí)現(xiàn)類型作為泛型參數(shù)。
在中間件類中,有兩個(gè)部分很重要:
1. 構(gòu)造函數(shù)接受RequestDelegate。當(dāng)調(diào)用此委托時(shí)會(huì)將當(dāng)前請(qǐng)求傳入下一個(gè)中間件。
2. 它擁有一個(gè)Invoke方法,接收HttpContext參數(shù)并返回空(Task)。當(dāng)需要用到中間件時(shí),框架會(huì)主動(dòng)調(diào)用這個(gè)方法。
注:在單獨(dú)類中實(shí)現(xiàn)中間件,并用UseMiddleware封裝起來(lái)是最佳實(shí)踐。
擴(kuò)展方法
需要注意擴(kuò)展方法的不同之處,RunXXX不會(huì)返回值,而UseXXX會(huì)返回值(IApplicationBuilder)。這是因?yàn)镽un()終止請(qǐng)求管道,而Use()可能會(huì)鏈接到其他的中間件。
順序
中間件按照它們?cè)贑onfigure()方法出現(xiàn)的順序依次被調(diào)用。而返回到客戶端的響應(yīng)也會(huì)經(jīng)歷相同的中間件管道。
原文:https://tahirnaushad.com/2017/08/14/asp-net-core-middleware/
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。