== 原文地址已不能访问,停止本系列更新==
问题
使用ASP.NET Core中间件创建Hello World
解决方案
从上一篇的空项目开始,如下修正Startup.cs
中的Configure()
方法
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env)
{
// setup request pipeline using middleware
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World! (Run)");
});
}
一个不错的练习使用扩展方法在IApplicationBuilder
上build pipeline:
// RunMiddlewareExtensions.cs
public static void RunHelloWorld(this IApplicationBuilder app)
{
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World! (Run)");
});
}
// Startup.cs
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env)
{
// setup request pipeline using middleware
app.RunHelloWorld();
}
上一段代码中我们使用IApplicationBuilder.Run()
配置中间件,另一种方法是用这个IApplicationBuilder.Run()
// UseMiddlewareExtensions.cs
public static IApplicationBuilder UseHelloWorld(
this IApplicationBuilder app)
{
return app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello World! (Use)\n");
await next();
});
}
// Startup.cs
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env)
{
// setup request pipeline using middleware
app.UseHelloWorld();
app.RunHelloWorld();
}
一个不错的练习如何使用中间件定义在单独的类中
public class HelloWorldMiddleware
{
private readonly RequestDelegate next;
public HelloWorldMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
await context.Response.WriteAsync("Hello World! (Use in Class)\n");
await this.next(context);
}
}
// UseMiddlewareExtensions.cs
public static IApplicationBuilder UseHelloWorldInClass(
this IApplicationBuilder app)
{
return app.UseMiddleware<HelloWorldMiddleware>();
}
// Startup.cs
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env)
{
// setup request pipeline using middleware
app.UseHelloWorld();
app.UseHelloWorldInClass();
app.RunHelloWorld();
}
讨论
中间件是一个拦截HTTP请求和响应消息的组件。我们创建这些组件连来构建我们的应用管道。
我们设置这个管道通过Configure()
方法,IApplicationBuilder
是参数,有下面三个方法:
-
Run():
添加一个中间件到管道, 不继续调用其他中间件 -
Use():
添加一个中间件,使用Lambda或者单独的类 -
Map():
根据请求路径添加中间件
Run
它用RequestDelegate
作为参数,当调用的时候用HttpContext
作为参数, 返回void
无类型,应为这个是短的请求管道。
Use
它用Func
作为参数, 也就是把HttpContext
和指针(Pointer)传到下一个中间件, 返回Task。 如果下个中间件没有调用,那他就是一个短的请求管道,和Run
一样。
UseMiddleware
当我们设置一个中间件的类时,我们要用UseMiddleware
去包装,提供我们的类和泛型参数。
独立的中间件类有两个关键内容:
- 构成方法接受
RequestDelegate
。 这个会调用请求到下一个中间件 - 它用
Invoke
接受参数HttpContext
返回Task
。 框架会根据需要调用中间件。
注:用独立的类实现中间件并且用UseMdilleware
是最佳实践
扩展方法
知道扩展方法的区别,RunXXX不支持返回值,然后UseXXX支持。这个是应为Run()
是短路径请求管道,而Use()
是以连的的形式连接其他中间件。
顺序
中间件调用顺序如他们在Configure()
方法里,按添加他们到管道的顺序。在响应方面,返回给客户端也是传递一样的中间件管道。
Source Code
GitHub: