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
)
比如在一个类库项目 <ProjectSdk="Microsoft.NET.Sdk">
里有这么一个引用 <PackageReferenceInclude="Microsoft.AspNetCore.Mvc.Core"Version="2.2.2"/>
,在 dotnetcore 3.0
并没有发布对应的 nuget
包,需要使用框架引用,示例如下:
<FrameworkReference Include="Microsoft.AspNetCore.App" />
如果是 Web 项目 <ProjectSdk="Microsoft.NET.Sdk.Web">
,Sdk
是 Web
的话直接把 targetFramework
更新的 netcoreapp3.0
就可以了,不需要再添加上面的引用了,项目里 <PackageReferenceInclude="Microsoft.AspNetCore.App"/>
的引用也可以直接移除了
Host
&& Environment
原来的 IHostingEnvironment
改为了 IWebHostEnvironment
,原来注入 IHostingEnvironment
的地方需要修改为注入 IWebHostEnvironment
原来 Program
里使用的 WebHostBuilder
改为 HostBuilder
并配置 ConfigureWebHostDefaults
,变更如下:
MVC
服务注册
3.0 里 MVC 对 Controller
和 RazorPages
以及 RazorViews
整理,注入服务的时候我们可以只注入自己需要的服务,如果是 WebAPI
项目可以只添加 Controller
需要的服务即可,对应的添加方式:
services.AddControllers(); // WebAPI
services.AddControllersWithViews(); // MVC
services.AddRazorPages(); // RazorPage
JSON 配置
asp.net core 3.0
默认使用微软新的 JSON
,但是推荐还是用 Newtonsoft.Json
,比较成熟而且对很多比较特殊的情况都有处理,已然成为了.NET
里 JSON
序列化的事实标准,使用方式如下:
- 引用
nuget
包Microsoft.AspNetCore.Mvc.NewtonsoftJson
- 配置使用
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);
});
这里没有用到 OperationFilter
,如果用到了 OperationFilter
,可能需要引入 Swashbuckle.AspNetCore.Filters
这个包,详细参考: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-cRelease./src/ActivityReservation.csproj-oout
命令:
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
,而且更新之后可能会遇到其他的问题,详见issue https://github.com/aspnet/EntityFrameworkCore/issues/18025
现在的项目使用 ef core2.1 + asp.net core3.0
运行
More
其他的地方应该也有需要修改的地方,欢迎补充
ASP.NET Core 3.0 发布
随着 .NET Core 3.0 的 GA,其中的 ASP.NET Core 与 Blazor 也相应得到增强,此版本的 ASP.NET Core 的一些重大新特性包括:
- 使用 C# 构建富交互客户端 Web 应用。
- 使用 gRPC 创建高性能后端服务。
- SignalR 现在支持自动重连接和客户端到服务器(client-to-server)流。
- 使用 OpenAPI 文档为 Web API 生成强类型的客户端代码。
- 通过框架集成了端点路由。
Kestrel
默认启用 HTTP/2。- 集成 Web API 和单页应用身份验证支持。
- 支持证书和
Kerberos
身份验证。 - 集成新的
System.Text.Json
序列化器。 - 新的通用主机设置了常见的托管服务,例如依赖项注入、配置和日志。
- 用于构建长期服务的新
Worker Service
模板。 - 为每秒请求、总请求、当前请求和失败请求创建了新的
EventCounters
。 - 现在会将托管在 IIS 中的启动错误报告给
Windows Event Log
。 - 请求管道集成
System.IO.Pipelines
。 - 整个技术栈的性能改进。
详情查看更新公告:
https://devblogs.microsoft.com/aspnet/asp-net-core-and-blazor-updates-in-net-core-3-0