ASP.NET Core 中间件
ASP.NET Core 引入了一个叫做中间件的新概念。中间件只是一个组件(类),它在 ASP.NET Core 应用程序中的每个请求上执行。在经典的 ASP.NET 中,HttpHandlers
和 HttpModules
是请求管道的一部分。中间件类似于 HttpHandlers
和 HttpModules
,两者都需要在每个请求中配置和执行。
通常,ASP.NET Core web 应用程序中会有多个中间件。它可以是通过 NuGet 添加的框架提供的中间件,也可以是您自己的定制中间件。我们可以在请求管道中设置中间件执行的顺序。每个中间件都添加或修改 http 请求,并可选地将控制权传递给下一个中间件组件。下图说明了中间件组件的执行。
中间件构建请求管道。下图说明了 ASP.NET Core 请求处理。
配置中间件
我们可以使用 IApplicationBuilder
实例在 Startup
类的 configure
方法中配置中间件。下面的实例使用 Run
方法添加了一个中间件,该方法根据每个请求返回字符串 "HelloWorld!"
public class Startup
{
public Startup()
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//使用 IApplicationBuilder 在这里配置中间件..
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
// other code removed for clarity..
}
}
了解 Run 方法
我们使用 Run
扩展方法添加中间件。以下是 Run
方法的签名:
public static void Run(this IApplicationBuilder app, RequestDelegate handler)
Run
方法是 IApplicationBuilder
上的一个扩展方法,并接受 RequestDelegate
参数。RequestDelegate
是处理请求的委托方法。以下是 RequestDelegate
签名。
public delegate Task RequestDelegate(HttpContext context);
如上所述,Run
方法接受一个方法作为参数,其签名应与 RequestDelegate
匹配。因此,该方法应接受 HttpContext
参数并返回 Task。因此,您可以在 Run
方法中指定 lambda 表达式或指定函数。上面 Run
方法中指定的 lambda 表达式与下面示例中的表达式类似。
public class Startup
{
public Startup()
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Run(MyMiddleware);
}
private Task MyMiddleware(HttpContext context)
{
return context.Response.WriteAsync("Hello World! ");
}
}
上面的 MyMiddleware
函数不是异步的,因此将阻塞线程直到它完成执行。因此,通过使用异步和等待来提高性能和可伸缩性,使其成为异步的。
// 为清晰起见,删除了其他代码
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Run(MyMiddleware);
}
private async Task MyMiddleware(HttpContext context)
{
await context.Response.WriteAsync("Hello World! ");
}
因此,上面的代码片段与下面的代码片段相同。
app.Run(async context => await context.Response.WriteAsync("Hello World!") );
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
因此,通过这种方式,我们可以使用 Run
方法配置中间件。
配置多个中间件
大多数情况下,ASP.NET Core 应用程序中将有多个中间件组件,这些组件将按顺序执行。Run
方法添加了一个终端中间件,因此它不能调用下一个中间件,因为它将是序列中的最后一个中间件。以下命令将始终执行第一个 Run
方法,并且永远不会到达第二个 Run
方法。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World From 1st Middleware");
});
// the following will never be executed
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World From 2nd Middleware");
});
}
要配置多个中间件,请使用 use()
扩展方法。它类似于 Run()
方法,只是它包含下一个参数来调用序列中的下一个中间件。考虑以下实例。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello World From 1st Middleware!");
await next();
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World From 2nd Middleware");
});
}
上面的实例将在浏览器中显示 Hello World From 1st Middleware!来自第二中间件的 Hello World!。
因此,我们可以使用 use()
方法按我们喜欢的顺序配置多个中间件。
通过 NuGet 添加内置中间件
ASP.NET Core 是一个模块化框架。通过 NuGet 安装不同的插件,我们可以在应用程序中添加所需的服务器端功能。有许多中间件插件可用于我们的应用程序。
以下是一些内置中间件:
中间件 | 描述 |
---|---|
Authentication | 添加身份验证支持。 |
CORS | 配置跨源资源共享。 |
Routing | 为 MVC 或 web 表单添加路由功能 |
Session | 添加对用户会话的支持。 |
StaticFiles | 添加对服务静态文件和目录浏览的支持。 |
Diagnostics | 添加对报告和处理异常和错误的支持。 |
Diagnostics 中间件
让我们安装并使用 Diagnostics 中间件。Diagnostics 诊断中间件用于报告和处理 ASP.NET Core 中的异常和错误,并诊断 Entity Framework Core 迁移错误。
打开项目,添加 Microsoft.AspNetCore.Diagnostics 依赖项。等待一段时间,直到 Visual Studio 恢复包。
该软件包包括以下中间件及其扩展方法。
中间件 | 扩展方法 | 描述 |
---|---|---|
DeveloperExceptionPageMiddleware | UseDeveloperExceptionPage() | 从管道中捕获同步和异步异常,并生成 HTML 错误响应。 |
ExceptionHandlerMiddleware | UseExceptionHandler() | 捕获异常,记录它们并在备用管道中重新执行。 |
StatusCodePagesMiddleware | UseStatusCodePages() | 检查状态代码在 400 和 599 之间的响应。 |
WelcomePageMiddleware | UseWelcomePage() | 显示根路径的欢迎页面。 |
我们可以调用各自的 Use* 扩展方法来在 Startup
类的 configure
方法中使用上述中间件。
让我们添加 welcomePage 中间件,它将显示根路径的欢迎页面。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseWelcomePage();
//other code removed for clarity
}
这样,我们可以使用不同的 use* 扩展方法来包含不同的中间件。