• asp.net core 3.0 更新简记


    asp.net core 3.0 更新简记

    Intro

    最近把活动室预约项目从 asp.net core 2.2 更新到了 asp.net core 3.0,记录一下,升级踩过的坑以及经验总结,包括但不限于

    • TargetFramework (netcoreapp2.2 需要更新为 netcoreapp3.0)
    • Dependency
    • Host/Environment
    • Mvc
    • Routing
    • Swagger
    • Dockerfile
    • EF(不推荐更新)

    TargetFramework 更新

    原来项目里的 netcoreapp2.x 版本需要更新为 netcoreapp3.0,原来有些基于 netstandard2.0 的项目的包如果有包更新之后依赖 netstandard2.1 可能需要更新为 netstandard2.1(非必须,看项目依赖)

    Dependency

    原来在 dotnetcore 2.x 版本时大部分的包以 nuget 的形式提供,可以直接通过 nuget 引用,从 dotnetcore 3.0 开始很多包不再发布 nuget 包,需要通过框架引用来引用包(FrameworkReference)

    比如在一个类库项目 <Project Sdk="Microsoft.NET.Sdk"> 里有这么一个引用 <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.2" />,在 dotnetcore 3.0 并没有发布对应的 nuget 包,需要使用框架引用,示例如下:

    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    

    如果是 Web 项目 <Project Sdk="Microsoft.NET.Sdk.Web">,Sdk 是 Web 的话直接把 targetFramework 更新的 netcoreapp3.0 就可以了,不需要再添加上面的引用了,项目里 <PackageReference Include="Microsoft.AspNetCore.App"/> 的引用也可以直接移除了

    Host && Environment

    原来的 IHostingEnvironment 改为了 IWebHostEnvironment,原来注入 IHostingEnvironment 的地方需要修改为注入 IWebHostEnvironment

    原来 Program 里使用的 WebHostBuilder 改为 HostBuilder 并配置 ``ConfigureWebHostDefaults ,变更如下:

    Program.cs

    MVC

    服务注册

    3.0 里 MVC 对 ControllerRazorPages 以及 RazorViews 整理,注入服务的时候我们可以只注入自己需要的服务,如果是 WebAPI 项目可以只添加 Controller 需要的服务即可,对应的添加方式:

    services.AddControllers(); // WebAPI
    services.AddControllersWithViews(); // MVC
    services.AddRazorPages(); // RazorPage
    

    JSON 配置

    asp.net core 3.0 默认使用微软新的 JSON,但是推荐还是用 Newtonsoft.Json,比较成熟而且对很多比较特殊的情况都有处理,已然成为了.NET 里 JSON 序列化的事实标准,使用方式如下:

    1. 引用 nuget 包 Microsoft.AspNetCore.Mvc.NewtonsoftJson

    2. 配置使用 Newtonsoft.Json

    services.AddControllersWithViews()
        .AddNewtonsoftJson(options =>
        {
            options.SerializerSettings.ContractResolver = new DefaultContractResolver();
            options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; // 设置时区为 UTC
        });
    

    Rounting

    asp.net core 3.0 推荐使用 endpoint rounting

    配置方式如下:

               app.UseStaticFiles();
    
                app.UseSwagger()
                    .UseSwaggerUI(c =>
                    {
                        // c.RoutePrefix = string.Empty; //
                        c.SwaggerEndpoint($"/swagger/{ApplicationHelper.ApplicationName}/swagger.json", "活动室预约系统 API");
                        c.DocumentTitle = "活动室预约系统 API";
                    });
                    
                app.UseRouting(); // 放在 UseStaticFiles 之后
    
                app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
    
                app.UseRequestLog();
                app.UsePerformanceLog();
    
                app.UseAuthentication();
                app.UseAuthorization(); // 放在 UseAuthentication 之后
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers(); // 属性路由
                    endpoints.MapControllerRoute("Notice", "/Notice/{path}.html", new
                    {
                        controller = "Home",
                        action = "NoticeDetails"
                    }); // 自定义路由
                    endpoints.MapControllerRoute(name: "areaRoute", "{area:exists}/{controller=Home}/{action=Index}"); // 区域路由
                    endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); // 默认路由
                });
    
    

    Swagger

    更新 swagger 依赖到最新的 5.0.0-rc-x 版本(还没发稳定版,需要显示预览版本才能看到)

    services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc(ApplicationHelper.ApplicationName, new Microsoft.OpenApi.Models.OpenApiInfo { Title = "活动室预约系统 API", Version = "1.0" });
    
        options.IncludeXmlComments(System.IO.Path.Combine(AppContext.BaseDirectory, $"{typeof(Models.Notice).Assembly.GetName().Name}.xml"));
        options.IncludeXmlComments(System.IO.Path.Combine(AppContext.BaseDirectory, $"{typeof(API.NoticeController).Assembly.GetName().Name}.xml"), true);
    });
    

    更多参考:
    https://www.cnblogs.com/laozhang-is-phi/p/11520048.html#autoid-6-0-0
    https://www.cnblogs.com/weihanli/p/ues-swagger-in-aspnetcore3_0.html

    Docker

    Dockerfile 里基础镜像需要更新到 3.0

    示例 dockerfile:

    FROM mcr.microsoft.com/dotnet/core/sdk:3.0-alpine AS build-env
    WORKDIR /src
    
    # Copy csproj and restore as distinct layers
    COPY ActivityReservation.Common/*.csproj ActivityReservation.Common/
    COPY ActivityReservation.Models/*.csproj ActivityReservation.Models/
    COPY ActivityReservation.DataAccess/*.csproj ActivityReservation.DataAccess/
    COPY ActivityReservation.Business/*.csproj ActivityReservation.Business/
    COPY ActivityReservation.Helper/*.csproj ActivityReservation.Helper/
    COPY ActivityReservation.WechatAPI/*.csproj ActivityReservation.WechatAPI/
    COPY ActivityReservation.AdminLogic/*.csproj ActivityReservation.AdminLogic/
    COPY ActivityReservation.API/*.csproj ActivityReservation.API/
    COPY ActivityReservation/ActivityReservation.csproj ActivityReservation/
    
    # RUN dotnet restore ActivityReservation/ActivityReservation.csproj
    ## diff between netcore2.2 and netcore3.0
    WORKDIR /src/ActivityReservation
    RUN dotnet restore
    
    # copy everything and build
    COPY . .
    RUN dotnet publish -c Release -o out ActivityReservation/ActivityReservation.csproj
    
    # build runtime image
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine
    
    LABEL Maintainer="WeihanLi"
    WORKDIR /app
    COPY --from=build-env /src/ActivityReservation/out .
    EXPOSE 80
    ENTRYPOINT ["dotnet", "ActivityReservation.dll"]
    

    修改基础镜像一般不会有什么问题,需要注意的是如果 dockerfile 里有用到 dotnet publish 且publish 的项目不在当前目录下,可能会遇到这样的问题,最后找不到要发布的文件。

    dotnet core 3.0 cli 有个 breaking change,如果要发布的项目不在当前目录下,在 2.x 版本是会发布到项目文件所在目录下的,但是 3.0 版本会发布在当前目录下,比如说执行dotnet publish -c Release ./src/ActivityReservation.csproj -o out命令:

    2.x版本会在 src目录下生成一个 out 文件夹

    3.0 版本会在当前目录下生成一个 out 文件夹,out文件夹和 src 同级

    详细问题可以参考 https://github.com/dotnet/cli/issues/12696

    EF

    EF Core 3.0 和 asp.net core 3.0 完全独立,可以在 asp.net core 3.0 的项目里使用 2.x 的 EF Core

    EF Core 3.0 有个 breaking change,不再隐式支持客户端渲染数据,这可以让你更清晰的知道哪些条件和在数据库执行的哪些条件是在本地执行的,但是实际试用下来,还是有很多问题的,在 EF 的基础上封装了一层,试用表达式树来拼接查询条件,但是最后执行的时候会有问题,但是简化后的条件实际上并不会在客户端执行任何过滤操作,所以暂时不推荐试用 ef core 3.0,而且更新之后可能会遇到其他的问题,比如在 docker alpine 中部署可能会遇到这个问题,详见issue https://github.com/aspnet/EntityFrameworkCore/issues/18025

    现在的项目使用 ef core2.1 + asp.net core3.0 运行

    More

    其他的地方应该也有需要修改的地方,欢迎补充

    Reference

  • 相关阅读:
    SpringBoot整合jsp
    SpringBoot常用application.properties配置
    SpringBoot入门
    vue cli创建vue项目
    vue 指令
    vue hello
    pytest doc
    atom
    java csvutil
    Django uuidfield 实现自动生成唯一列,并设置为主键
  • 原文地址:https://www.cnblogs.com/weihanli/p/notes-on-update-aspnetcore3_0.html
Copyright © 2020-2023  润新知