第一阶段迁移已完成。

已实现:
ASP.NET Core 10 分层解决方案:[Eis.slnx](C:/Users/BI/Documents/EIS-dotnet/Eis.slnx)
ASP.NET Core 统一入口与健康检查:[Program.cs](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Web/Program.cs)
原前端静态资源无修改托管
未迁移 API 自动转发至旧 Node 服务,兼容 JSON、Cookie、请求体和文件下载
可重复执行的端到端测试:[smoke-dotnet-migration.ps1](C:/Users/BI/Documents/EIS-dotnet/scripts/smoke-dotnet-migration.ps1)
迁移进度与运行说明:[MIGRATION.md](C:/Users/BI/Documents/EIS-dotnet/MIGRATION.md)
验证结果:
This commit is contained in:
2026-07-22 18:45:54 +08:00 Unverified
parent ecb3dc63ed
commit 241fa8a6d7
20 changed files with 680 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
using System.Net;
using Eis.Infrastructure.Migration;
using Eis.Web.Frontend;
using Eis.Web.Legacy;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options => options.AddServerHeader = false);
builder.Services.Configure<LegacyNodeOptions>(builder.Configuration.GetSection(LegacyNodeOptions.SectionName));
builder.Services.AddHttpClient<LegacyApiProxy>((services, client) =>
{
var options = services.GetRequiredService<Microsoft.Extensions.Options.IOptions<LegacyNodeOptions>>().Value;
client.BaseAddress = options.BaseUrl;
client.Timeout = TimeSpan.FromSeconds(30);
client.DefaultRequestHeaders.UserAgent.ParseAdd("Eis.AspNetCore.Migration/1.0");
}).ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None,
UseCookies = false
});
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.Use(async (context, next) =>
{
context.Response.Headers.XContentTypeOptions = "nosniff";
context.Response.Headers.XFrameOptions = "DENY";
context.Response.Headers["Referrer-Policy"] = "same-origin";
await next();
});
app.MapGet("/health/live", () => Results.Json(new
{
status = "healthy",
service = "Eis.Web",
framework = ".NET 10"
}));
app.MapGet("/health/migration", async (LegacyApiProxy proxy, CancellationToken cancellationToken) =>
{
var legacyAvailable = await proxy.IsAvailableAsync(cancellationToken);
var statusCode = legacyAvailable ? StatusCodes.Status200OK : StatusCodes.Status503ServiceUnavailable;
return Results.Json(new
{
status = legacyAvailable ? "healthy" : "degraded",
legacyApiAvailable = legacyAvailable,
features = MigrationFeatureCatalog.Current
}, statusCode: statusCode);
});
string[] methods =
[
HttpMethods.Get,
HttpMethods.Head,
HttpMethods.Post,
HttpMethods.Put,
HttpMethods.Patch,
HttpMethods.Delete,
HttpMethods.Options
];
app.MapMethods("/api/{**path}", methods, (HttpContext context, LegacyApiProxy proxy) => proxy.ForwardAsync(context));
app.MapFrontendAssets();
app.Run();
public partial class Program;