增量ASP.NET 迁移到 ASP.NET Core

内容纲要

ASP.NET Core 是适用于 .NET 的现代统一 Web 框架,可满足您所有的 Web 开发需求。它是完全开源的,跨平台的,并且充满了创新功能:Blazor,SignalR,gRPC,最小API等。在过去几年中,我们看到许多客户希望将其应用程序从 ASP.NET 迁移到 ASP.NET Core。迁移到 ASP.NET Core 的客户已经实现了巨大的成本节约,包括 Azure Cosmos DB、Microsoft Graph 和 Azure Active Directory。

我们也看到了客户在经历这一旅程时面临的许多挑战。这包括 ASP.NET Core 上不可用的依赖项以及此迁移所需的时间。我们自己也一直在努力帮助作为客户的您简化此迁移,包括过去一年中在 .NET 升级助手上的工作。今天,我们宣布了更多的工具、库和模式,这些工具、库和模式将允许应用程序以更少的工作量和增量的方式迁移到 ASP.NET Core。这项工作将在 GitHub 上以新的存储库完成,我们很高兴与社区合作,以确保我们构建正确的适配器和工具集。

当前挑战

这一进程缓慢和困难的原因有很多,我们退后一步,看看外部和内部伙伴的例子,了解它们最紧迫的关切是什么。这归结为我们想要解决的几个关键主题:

  • 大型应用程序如何以增量方式迁移到 ASP.NET Core,同时仍能为其业务进行创新并提供价值?
  • 如何才能在不重复和完全重写的情况下对编写反对的库进行现代化改造?System.Web.HttpContext

让我深入探讨这些问题中的每一个,以分享我们所看到的以及我们正在开展哪些工作来帮助。

增量迁移

许多大型应用程序每天都在用于业务关键型应用程序。这些需要继续运行,并且不能被搁置,以便可能长时间迁移到 ASP.NET Core。这意味着,在进行迁移时,应用程序仍需要做好生产准备,并且可以像往常一样添加和部署新功能。

已被证明适用于这种过程的模式是扼杀者无花果模式。扼杀者无花果图案用于一次替换现有的遗留系统一块,直到整个系统更新并且可以停用旧系统。这种模式在抽象中相当容易掌握,但经常会出现如何在实践中实际使用它的问题。这是增量迁移过程的一部分,我们希望围绕该过程提供具体指导。

System.Web.dll在支持库中的使用

ASP.NET 应用依赖于 System.Web 中的 API.dll来访问 Cookie、标头、会话和当前请求中的其他值等内容。ASP.NET 应用通常依赖于依赖于这些 API 的库,如 、 、 等。但是,这些类型在 ASP.NET Core 中不可用,并且在现有代码库中重构此代码非常困难。HttpContextHttpRequestHttpResponse

为了简化迁移过程的这一部分,我们引入了一组适配器,这些适配器实现了 Against 的形状。这些适配器包含在新包中。此包将允许您继续使用现有的逻辑和库,同时另外面向 .NET Standard 2.0、.NET Core 3.1 或 .NET 6.0 以支持在 ASP.NET Core 上运行。System.Web.HttpContextMicrosoft.AspNetCore.Http.HttpContextMicrosoft.AspNetCore.SystemWebAdapters

让我们看一下增量迁移对于应用程序可能是什么样子的。我们将从一个 ASP.NET 应用程序开始,该应用程序具有使用基于System.Web的API的支持库:

此应用程序承载在 IIS 上,并围绕它有一组用于部署和维护的进程。迁移过程旨在迁移到 ASP.NET Core,而不会影响当前部署。

第一步是引入一个基于 ASP.NET Core的新应用程序,该应用程序将成为切入点。流量将进入 ASP.NET Core 应用,如果应用无法匹配路由,它将通过 YARP 将请求代理到 ASP.NET 应用程序。大多数代码将继续位于 ASP.NET 应用程序中,但 ASP.NET Core 应用现在已设置为开始将路由迁移到。

这个新应用程序可以部署到任何有意义的地方。使用 ASP.NET Core,您有多种选择:IIS / Kestrel,Windows / Linux等。但是,保持部署类似于 ASP.NET 应用将简化迁移过程。

为了开始移动依赖于的业务逻辑,需要针对 来构建库。这允许使用 System.Web API 的库面向 .NET Framework、.NET Core 或 .NET Standard 2.0。这将确保库使用的表面积同时适用于 ASP.NET 和 ASP.NET Core:HttpContextMicrosoft.AspNetCore.SystemWebAdapters

现在,我们可以开始将路线一次移动到 ASP.NET Core应用。这些可以是 MVC 或 Web API 控制器(甚至是来自控制器的单个方法)、Web 窗体 ASPX 页、HTTP 处理程序或路由的其他一些实现。一旦该路线在 ASP.NET Core应用程序中可用,它将从那里进行匹配和服务。

在此过程中,将确定必须移动才能在 .NET Core 上运行的其他服务和基础结构。一些选项包括(按可维护性顺序列出):

  1. 将代码移动到共享库
  2. 链接新项目中的代码
  3. 复制代码

随着时间的推移,核心应用程序将开始处理比 .NET Framework 应用程序更多的路由:

在此过程中,您可能在 ASP.NET Core 和 ASP.NET Framework 应用程序中都有该路由。这可以让您执行一些A / B测试,以确保功能符合预期。

一旦不再需要 .NET Framework 应用程序,它可能会被删除:

此时,应用程序作为一个整体在 ASP.NET 核心应用程序堆栈上运行,但它仍在使用此存储库中的适配器。此时,目标是在应用程序完全依赖于 ASP.NET Core 应用程序框架之前,删除适配器的使用:

通过将应用程序直接放在 ASP.NET Core API 上,您可以获得 ASP.NET Core 的性能优势,并利用适配器后面可能不可用的新功能。

开始

现在我们已经为Strangler Fig模式和System.Web适配器奠定了基础,让我们来一个应用程序,看看我们需要做些什么来应用它。

为了解决这个问题,我们将使用预览Visual Studio扩展,该扩展有助于完成我们需要执行的一些步骤。你还需要最新的 Visual Studio Preview 才能使用此扩展。

我们将采用 ASP.NET MVC 应用并开始迁移过程。首先,右键单击项目并选择“迁移项目”,这将打开一个工具窗口,其中包含用于开始迁移的选项。迁移向导将打开:

可以使用新项目设置解决方案,也可以选择要使用的现有 ASP.NET Core 项目。这将对 ASP.NET 核心项目做一些事情:

  • 添加并添加其初始配置以访问原始框架应用(称为Yarp.ReverseProxyfallback)
  • 将环境变量添加到 launchSettings.json,以设置访问原始框架应用所需的环境变量
  • 添加 ,注册服务,并为其插入中间件Microsoft.AspNetCore.SystemWebAdapters

ASP.NET Core 应用的启动代码现在将如下所示:

using Microsoft.AspNetCore.SystemWebAdapters;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSystemWebAdapters();
builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

// Add services to the container.
builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();
app.UseSystemWebAdapters();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapReverseProxy();

app.Run();

此时,你可以运行 ASP.NET Core 应用,它将代理所有请求到核心应用中不匹配的框架应用。如果使用默认模板,您将看到以下行为:

如果你去 ,它将显示 ASP.NET Core应用程序://Home/Index

如果您转到 ASP.NET Core 上不存在但存在于框架应用上的页面,则该页面现在将显示:

请注意,URL 是相同的 (),但会在需要时代理对框架应用的请求。现在,你已设置为开始将路由引入核心应用,包括引用 System.Web.dll的库。https://localhost:7234

代理支持

框架应用现在将位于反向代理的下游。这意味着某些值(如请求 URL)将有所不同,因为它不会使用公共入口点。若要更新这些值,请使用 Global.asax.cs 或 Global.asax.vb中的以下代码打开框架应用的代理支持:

protected void Application_Start()
{
  Application.AddSystemWebAdapters()
      .AddProxySupport(options => options.UseForwardedHeaders = true);
}

此更改可能会对应用程序造成其他影响。整理出来将是实现扼杀者无花果模式的初始过程的一部分。请提交此处遇到的尚未记录的挑战的问题。

会话支持

会话在 ASP.NET 和 ASP.NET 核心之间的工作方式非常不同。为了在两者之间提供桥梁,适配器中的会话支持是可扩展的。为了在 ASP.NET Core 和 ASP.NET 之间具有相同的会话行为(和共享会话状态),我们提供了一种使用框架应用中的值填充核心上的会话状态的方法。

此设置将向框架应用添加一个处理程序,该处理程序将允许核心应用查询会话状态。这具有应考虑的潜在性能和安全性问题,但它允许在两个应用之间共享会话状态。

要进行此设置,请将包添加到两个应用程序中。Microsoft.AspNetCore.SystemWebAdapters.SessionState

接下来,在 ASP.NET Core 应用上添加服务:

builder.Services.AddSystemWebAdapters()
    .AddJsonSessionSerializer(options =>
    {
        // Serialization/deserialization requires each session key to be registered to a type
        options.RegisterKey<int>("test-value");
        options.RegisterKey<SessionDemoModel>("SampleSessionItem");
    })
    .AddRemoteAppSession(options =>
    {
        // Provide the URL for the remote app that has enabled session querying
        options.RemoteApp = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);

        // Provide a strong API key that will be used to authenticate the request on the remote app for querying the session
        options.ApiKey = "strong-api-key";
    });

这将注册密钥,以便会话管理器知道如何序列化和反序列化给定密钥,并告诉它远程应用程序的位置。请注意,这现在要求对象可由 序列化,这可能需要更改存储在会话中的某些对象。System.Text.Json

对于一直使用会话值的代码库来说,标识键可能具有挑战性。第一个预览版要求你注册它们,但无助于识别它们。在将来的更新中,我们计划记录有用的消息,如果找到未注册的密钥,可以选择抛出。

最后,在 Global.asax 中以类似的方式在框架应用上添加以下代码:

protected void Application_Start()
{
    Application.AddSystemWebAdapters()
        .AddRemoteAppSession(
            options => options.ApiKey = "some-strong-key-value",
            options => options.RegisterKey<int>("some-key"));
}

设置完成后,您将能够按预期使用!(int)HttpContext.Session["some-key"]

总结

今天,我们将介绍一些工具和库,以帮助解决增量迁移问题,并帮助您更快、更轻松地推进 ASP.NET 应用程序。

在这个领域还有更多工作要做,我们希望对您有所帮助。我们正在GitHub上开发这个 https://github.com/dotnet/systemweb-adapters,并欢迎问题和PR来推动这一进程。

给TA打赏
共{{data.count}}人
人已打赏
.NET

.NET Framework 2022 年 5 月累积更新

2022-5-31 17:48:56

.NET

OneService 前往 .NET 6

2022-6-14 16:29:34

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索