将 HTTP 处理程序和 HTTP 模块迁移到 ASP.NET Core 中间件的基本步骤。






4.76/5 (6投票s)
迁移 HTTP 处理程序和 HTTP 模块到 ASP.NET Core 中间件
引言
我的团队正在将 Angular JS 1.5.XX 和 MVC 5 迁移到使用 Angular 2.0 的 .NET Core Web App。在迁移过程中,我们意识到项目中使用了 HTTP 处理程序。我们决定也迁移它们,尽管这是一个大胆的决定 ;-)。在迁移过程中,我们遇到了一些挑战,但最终成功迁移了。然后我决定写一篇文章,对迁移过程进行一个高层次的介绍。这篇文章就是这样诞生的 :-)。
本文提供了在将 HTTP 处理程序和模块迁移到 ASP.NET Core 中间件时需要遵循的基本步骤。本文不会深入探讨 HTTP 处理程序和模块,也不会深入探讨 ASP.NET Core 中间件。我只会使用 Response 对象在 Web 浏览器中显示输出。我希望这篇文章保持非常简单。在实际场景中,处理程序和模块涉及应用程序的关键逻辑。我的目的是通过代码示例提供 HTTP 处理程序和模块以及 ASP.NET Core 中间件的高层次介绍,因为我认为这将有助于初步理解 ASP.NET Core 中间件。
在本文中,我使用了 VS 2015 Update 3。
我为本文规划了以下内容:
- HTTP 处理程序
- HTTP 模块
- 创建一个带有示例 HTTP 处理程序和模块的 VS 项目
- ASP.NET 中间件及其关键方法
- 创建一个带有示例 ASP.NET Core 中间件的 VS 项目
- 将步骤 #3 中创建的 HTTP 处理程序和模块迁移到 ASP.NET 中间件
- HTTP 处理程序和模块与 ASP.NET Core 中间件之间的主要区别
1. HTTP 处理程序
HTTP 处理程序会在 Web 服务器收到的每个请求的响应中运行。最常见的例子是 *.aspx* 或 *.rss* 提要。可以根据自己的需求创建 HTTP 处理程序,并将输出渲染到 Web 浏览器。它们是通过实现 `IHttpHandler` 的 `ProcessRequest()` 来创建的。
public class CustomReportHandler : IHttpHandler
{
#region IHttpHandler Members
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
var response = context.Response;
response.Write
("<h2>This handler is written for processing files with .report extension<h2>");
//more logic follows...
}
#endregion
}
2. HTTP 模块
HTTP 模块是为应用程序收到的每个请求调用的类。它们可以访问 HTTP 管道的生命周期事件。可以通过实现 `IHttpModule` 的 `Init()` 来创建自定义的 HTTP 模块。
public class CustomModule : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
//clean-up code here.
}
public void Init(HttpApplication context)
{
context.BeginRequest += (source, arguments) =>
{
var httpApplication = (HttpApplication)source;
var httpContext = httpApplication.Context;
httpContext.Response.Write("<h3>Custom module started the begin request</h3>");
// More logic goes here....
//httpApplication.CompleteRequest();// if you want to short-circut the request,
// then call the CompleteRequest().
};
context.EndRequest += (source, arguments) =>
{
var httpApplication = (HttpApplication)source;
var httpContext = httpApplication.Context;
httpContext.Response.Write("<h3>Custom module completed the request</h3>");
// More logic goes here....
};
}
#endregion
3. 创建一个带有示例 HTTP 处理程序和模块的 VS 项目
- 打开 VS 2015,创建一个名为 "
MigratingHttpHandlersModulesToMiddleware
" 的空白解决方案。您可以随意命名。 - 添加一个名为 "
CustomHandlersModules
" 的新项目(ASP.NET Web 应用程序),并选择 "Empty" 模板。 - 创建一个名为 "
CustomReportHandler
" 的类,并实现 `IHttpHandler`。您可以从上面的 HTTP 处理程序部分复制代码片段。- 使用以下条目更新 `Web.config` 文件:
<!--Under configuration - system.webServer - handlers section add below:--> <add name="CustomReportHandler" verb="*" path="*.report" type="CustomHandlersModules.CustomReportHandler" resourceType="Unspecified"/>
- 此处理程序将在 Web 应用程序收到以 `.report` 扩展名结尾的资源请求时运行。
- 按 Ctrl + F5,访问 `https://:29342/test.report`。您的端口可能不同。
- 您将在 Web 浏览器中看到输出:This handler is written for processing files with .report extension。
- 使用以下条目更新 `Web.config` 文件:
- 创建一个名为 "
CustomModule
" 的类,并实现 `IHttpModule`。您可以从上面的 HTTP 模块部分复制代码片段。- 使用以下条目更新 `Web.config` 文件:
<!--Under configuration - system.webServer - modules section add below:--> <add name="CustomModule" type="CustomHandlersModules.CustomModule"/>
- 按 Ctrl + F5,访问 `https://:29342/test.report`。您的端口可能不同。
- 您将在 Web 浏览器中看到以下输出:
Custom module started the begin request. This handler is written for processing files with .report extension. Custom module completed the request.
- 使用以下条目更新 `Web.config` 文件:
在 Web 浏览器中。
4. ASP.NET 中间件及其关键方法
到目前为止,我们看到的是我们都习惯于实现的 Handler 和 Module 的实现。现在,我们将进入 ASP.Core 的有趣主题——中间件。
什么是中间件?它们是添加到应用程序管道中的代码。代码会应用一些逻辑,并在管道中处理请求。
为了实现这一点,我们可以使用传递给 Request Delegate 的 Application Builder 的 4 个方法:
Run
:这将终止 http 管道。Use
:将中间件添加到请求管道。Map
:这用于根据请求的路径匹配请求委托。MapWhen
:此方法支持基于谓词的中间件分支,允许独立的管道。
创建核心应用程序时,入口点是 `Startup.cs`。此类有两个方法:`Configure()` 和 `ConfigureServices()`。`Configure()` 是定义和执行所有中间件的地方。`ConfigureServices()` 是应用程序使用的所有服务的存放处。
您可以在 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware 找到更多相关文档。
现在我们有了基本了解,让我们开始创建 ASP.NET Core 应用程序。
5. 创建一个带有示例 ASP.NET Core 中间件的 VS 项目
- 打开 VS 2015 解决方案,添加一个名为 "
CustomMiddlewareForHttpHandlersModules
" 的新项目,模板为 ASP.NET Core Web Application (.NET Core),并选择 Blank 模板。 - 在 `Startup.cs` 中,在 `app.Run()` 之前添加以下内容:
app.Use(async (context, next) => { await context.Response.WriteAsync("Custom call!!!!! <br/>"); await next.Invoke(); });
- 按 Ctrl + F5。您将在 Web 浏览器中看到上述输出以及 "Hello World!"。
既然我们已经了解了基本中间件,让我们开始迁移 Handler,然后再迁移 Module。
6. 将步骤 #3 中创建的 HTTP 处理程序和模块迁移到 ASP.NET 中间件
6a. 迁移 HTTP 处理程序
在本节中,我们将迁移在步骤 #3 中创建的处理程序。
- 添加一个名为 "
CustomHanlderMiddleware
" 的类,并在其中包含以下代码:public class CustomHanlderMiddleware { private RequestDelegate _next; public CustomHanlderMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { await context.Response.WriteAsync ("<h2>This handler is written for processing files with .report extension<h2>"); //more logic follows... } }
- 为了在请求管道中使用上面创建的 `CustomHandlerMiddleware`,我们需要创建一个 `ApplicationBuilder` 的扩展方法。创建一个名为 "
CustomMiddlewareExtensions
" 的类,并按如下方式放置代码:public static class CustomMiddlewareExtensions { public static IApplicationBuilder UseCustomHanlderMiddleware (this IApplicationBuilder builder) { return builder.UseMiddleware<CustomHanlderMiddleware>(); } }
- 在 `Startup.cs` 中,将以下代码放在 `app.Run()` 的正上方。
app.Use(async (context, next) => { await context.Response.WriteAsync("Custom call!!!!! <br/>"); await next.Invoke(); }); // For Handler app.MapWhen(context => context.Request.Path.ToString().EndsWith(".report"), appBuilder => { appBuilder.UseCustomHanlderMiddleware(); }); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); });
- `next.Invoke()` 方法用于调用管道中的下一个请求委托。通过不调用 `next` 可以终止调用。
6b. 迁移 HTTP 模块
在本节中,我们将迁移在步骤 #3 中创建的模块。
- 添加一个名为 "
CustomModuleMiddleware
" 的类。并在其中包含以下代码:public class CustomModuleMiddleware { private RequestDelegate _next; public CustomModuleMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { await context.Response.WriteAsync("<h3>Custom module started the begin request</h3>"); await _next.Invoke(context); await context.Response.WriteAsync("<h3>Custom module completed the request</h3>"); } }
- 在 `CustomerMiddlewareExtensions.cs` 中,创建一个将中间件添加到请求管道的扩展方法。该类应如下所示:
public static class CustomMiddlewareExtensions { public static IApplicationBuilder UseCustomHanlderMiddleware (this IApplicationBuilder builder) { return builder.UseMiddleware<CustomHanlderMiddleware>(); } public static IApplicationBuilder UseCustomModuleMiddleware (this IApplicationBuilder builder) { return builder.UseMiddleware<CustomModuleMiddleware>(); } }
- 在 `Startup.cs` 中,将以下代码放在 `app.Run()` 的正上方。
app.Use(async (context, next) => { await context.Response.WriteAsync("Custom call!!!!! <br/>"); await next.Invoke(); }); // For Module app.UseCustomModuleMiddleware(); // For Handler app.MapWhen(context => context.Request.Path.ToString().EndsWith(".report"), appBuilder => { appBuilder.UseCustomHanlderMiddleware(); }); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); });
- 按 Ctrl + F5。访问 `https://:31736/test.report`。
最后,我们将 Handler 和 Module 迁移到了 ASP.NET Core 中间件。要查看相同输出,您可以注释掉 `app.Use()` 和 `app.Run()`。
7. HTTP 处理程序和模块与 ASP.NET Core 中间件之间的主要区别
- Web.config
- 对于 Handler 和 Modules:我们需要修改
- 对于 ASP.NET Core:无需修改
- 应用程序生命周期
- 对于 Handler 和 Modules:我们有它
- 对于 ASP.NET Core:它不存在
- 请求管道终止
- 对于 Handler 和 Modules:`CompleteRequest()` 会终止请求
- 对于 ASP.NET Core:通过不将请求委托传递给下一个组件
关注点
- 我们认为 ASP.NET Core 中间件是 HTTP 处理程序和模块的组合。
- 在 `Startup.cs` 的 `configure()` 方法中放置 `app.Use()` 方法是中间件执行的关键。
- ASP.NET Core 提供了多种开箱即用的中间件。例如:身份验证、会话、CORS 等。
结束语
我已将包含不同中间件(主要是内存中的会话)和数据传递的代码放在 GitHub 上。代码可在 https://github.com/psdinesh/MigratingHttpHandlersModulesAspNetCoreMiddleware 找到。