如何将ASP.NET Core 2.1启动代码升级至3.1版本
ASP.NET Core 2.1 升级至 3.1 适配指南
一、项目文件(.csproj)基础确认
你已完成目标框架修改,保持如下配置即可:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> </Project>
二、Startup 代码适配调整
1. ConfigureServices 方法修改
ASP.NET Core 3.0+ 引入端点路由机制,MVC服务注册方式变更,同时部分配置细节调整:
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { var connection = Configuration.GetConnectionString("DBconnection"); services.AddDbContext<HoshmandDBContext>(option => option.UseSqlServer(connection)); // 认证配置核心逻辑保留,注意需引用 Microsoft.AspNetCore.Authentication.Cookies services.AddAuthentication(option => { option.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; option.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; option.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie(options => { options.LoginPath = "/Logins/UserLogin/"; options.AccessDeniedPath = "/AccessDenied"; // 3.1 中 Cookie.Expiration 已过时,改用 ExpireTimeSpan options.ExpireTimeSpan = new TimeSpan(10, 0, 0); }); services.AddDistributedMemoryCache(); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromHours(2); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); services.ConfigureApplicationCookie(option => { option.ExpireTimeSpan = TimeSpan.FromMinutes(540); }); services.AddAuthorization(options => { options.AddPolicy("HasAccess", policy => policy.AddRequirements(new HasAccessRequirment())); }); services.AddTransient<IAuthorizationHandler, HasAccessHandler>(); services.AddTransient<IMvcControllerDiscovery, MvcControllerDiscovery>(); // 替换 AddMvc() 为 AddControllersWithViews(),明确注册MVC控制器和视图服务 services.AddControllersWithViews() .SetCompatibilityVersion(CompatibilityVersion.Version_3_1); } // 2. Configure 方法修改:调整中间件顺序,启用端点路由 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); // 3.1 要求 UseRouting 必须在 UseAuthentication、UseAuthorization 之前 app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseCookiePolicy(); app.UseSession(); // 替换 UseMvc 为 UseEndpoints,使用端点路由配置规则 app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=UserProfiles}/{action=Index}/{id?}"); }); } }
关键变更:
- 用
AddControllersWithViews()替代AddMvc(),明确注册所需MVC服务 - 调整中间件顺序:
UseRouting需前置在认证、授权中间件之前 - 用
UseEndpoints替代UseMvc配置路由,符合3.0+端点路由规范 - 替换过时的
Cookie.Expiration为ExpireTimeSpan
三、NuGet 包引用更新
ASP.NET Core 3.1 中多数基础框架包已整合到 Microsoft.AspNetCore.App 元包,无需单独引用。更新后的包引用如下:
<ItemGroup> <!-- 第三方包可保留,建议升级到兼容.NET Core 3.1的版本 --> <PackageReference Include="BCrypt-Core" Version="2.0.0" /> <PackageReference Include="ClosedXML" Version="0.97.0" /> <PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.8.0" /> <!-- Entity Framework Core 升级到3.1稳定版本 --> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.31"> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.31" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.31"> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> <!-- 代码生成工具升级到3.1版本 --> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.6" /> <!-- 其他第三方包保持或升级到兼容版本 --> <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.19" /> </ItemGroup> <!-- 移除DotNetCliToolReference,3.0+改用PackageReference管理工具 -->
关键变更:
- 移除所有单独的
Microsoft.AspNetCore.*包,Microsoft.NET.Sdk.Web已自动引用Microsoft.AspNetCore.App元包 - Entity Framework Core相关包统一升级到3.1.x稳定版本
- 移除
DotNetCliToolReference,代码生成工具通过Microsoft.VisualStudio.Web.CodeGeneration.Design提供 - 第三方包建议升级到兼容.NET Core 3.1的版本
四、控制器代码优化
1. UserProfilesController 优化
移除不必要的异步包装,规范异步逻辑:
[Authorize] public async Task<IActionResult> Index(bool? passIsChanged = null) { if (passIsChanged != null) { ViewBag.isSuccessed = passIsChanged; } if (!int.TryParse(User.Identity.Name, out int id)) { return RedirectToAction("UserLogin", "Logins"); } var user = await _context.UserAccountTbs.FirstOrDefaultAsync(a => a.UserId == id); if (user == null) { return RedirectToAction("UserLogin", "Logins"); } var userprofile = new UserProfile { UserId = user.UserId, Name = user.FirstName }; return View(userprofile); }
优化点:
- 用异步查询
FirstOrDefaultAsync替代同步方法 - 增加
int.TryParse防止转换异常 - 移除多余的
await Task.FromResult,直接返回视图
2. LoginsController 优化
简化异步逻辑,补充完整登录流程:
public LoginsController(HoshmandDBContext context) : base(context) { } [HttpGet] public IActionResult UserLogin() { return View(new Login()); } [HttpPost] [AllowAnonymous] public async Task<IActionResult> UserLogin([FromForm] Login currentUser) { if (ModelState.IsValid) { var properties = new AuthenticationProperties { IsPersistent = currentUser.RememberMe, AllowRefresh = false, ExpiresUtc = DateTimeOffset.UtcNow.AddDays(10) }; var user = await _context.UserAccountTbs.FirstOrDefaultAsync(a => a.UserName.Equals(currentUser.UserName)); if (user == null) { TempData["UserLoginFailed"] = "Login Failed: Please Enter Correct Credential"; return View(); } else { // 结合BCrypt-Core验证密码 if (BCrypt.Net.BCrypt.Verify(currentUser.Password, user.PasswordHash)) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, user.UserId.ToString()) }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, properties); return RedirectToAction("Index", "UserProfiles"); } else { TempData["UserLoginFailed"] = "Login Failed: Incorrect Password"; return View(); } } } return View(currentUser); }
优化点:
- 同步方法直接返回
IActionResult,无需Task.Run包装 - 用异步查询替代同步方法
- 补充完整的密码验证和登录逻辑
内容的提问来源于stack exchange,提问作者Hedayat Hoshmand
相关产品推荐
相关产品推荐

