You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 08:25:29