abp项目.net版本升级
系统基于abp框架,.net版本为.net core 2.1,升级之后为.NET 6.0
1.升级项目的目标框架和依赖包
- 项目列表如下
- 升级顺序如下
- HPE_ProjectManagement_WebApi.Web (需要修改的东西最多)
- HPE_ProjectManagement_WebApi.Utility
- HPE_ProjectManagement_WebApi.Core
- HPE_ProjectManagement_WebApi.EntityFrameworkCore
- HPE_ProjectManagement_WebApi.Application
依次升级
- 升级目标框架之后需要项目引用的包都需要进行升级,可以使用nuget一键升级。一键升级可能会存在部分包的版本有问题,这个需要等发现问题在具体看。
2.代码修改
- 如果是全新的.net6项目是没有startup文件的,配置放在Program.cs中,这里我们不修改Program.cs,依然使用startup.cs来配置项目
- .net版本升级后,一些原有的api都需要更新掉。
2.1 startup.cs文件修改
具体修改的点如下
- 升级后使用automapper10.0,需要注册服务。services.AddAutoMapper(typeof(MappingProfile));
- AddJsonOptions() 方法修改为 AddNewtonsoftJson()
- Info类删除,使用OpenApiInfo代替
- app.UseMvc()修改为app.UseRouting()和app.UseEndpoints()
- app.UseAuthentication()需要放在app.UseRouting()和app.UseEndpoints()之间
using System;
using Abp.AspNetCore;
using Abp.Castle.Logging.Log4Net;
using Abp.EntityFrameworkCore;
using HPE_ProjectManagement_WebApi.EntityFrameworkCore;
using Castle.Facilities.Logging;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Swashbuckle.AspNetCore.Swagger;
using Panda.DynamicWebApi;
using System.IO;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using HPE_ProjectManagement_WebApi.Application;
using HPE_ProjectManagement_WebApi.Application.Authorization;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using Microsoft.Extensions.Configuration;namespace HPE_ProjectManagement_WebApi.Web.Startup
{public class Startup{private readonly IWebHostEnvironment _hostingEnvironment;public Startup(IWebHostEnvironment env){_hostingEnvironment = env;}public IServiceProvider ConfigureServices(IServiceCollection services){//Configure DbContextservices.AddAbpDbContext<HPE_ProjectManagement_WebApiDbContext>(options =>{DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ConnectionString);});services.AddControllersWithViews();// 添加后解决post请求返回400错误services.AddControllers().AddNewtonsoftJson();// 注册Session 过期时间300分钟services.AddSession(options =>{options.IdleTimeout = TimeSpan.FromMinutes(300);});// 加载AutoMapper10.0services.AddAutoMapper(typeof(MappingProfile));// 读取配置文件SecurityKey 配置jwtvar securityKey = ConfigurationHelper.GetSingleNode("SecurityKey");services.AddAuthentication(option =>{option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(option =>{option.TokenValidationParameters = new TokenValidationParameters{ValidIssuer = "Issuer",ValidAudience = "Audience",ValidateIssuer = true,ValidateLifetime = true,IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey)),// 缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间,如果不配置,默认是5分钟ClockSkew = TimeSpan.FromSeconds(3)};});// 注册IHttpClientFactory服务services.AddHttpClient();// needed to load configuration from appsettings.jsonservices.AddOptions();// 添加动态apiservices.AddDynamicWebApi();// 添加身份验证服务services.AddMvcCore().AddAuthorization();// 全局添加Authorize过滤 services.AddMvc(options =>{options.Filters.Add(new CustomAuthorizeFilter());}).AddNewtonsoftJson(options =>//解决接口返回的时间带T的问题{options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";}).AddXmlSerializerFormatters();//添加xml参数;// 添加swagger配置services.AddSwaggerGen(options =>{options.SwaggerDoc("v1", new OpenApiInfo { Title = "项目管理平台 WebApi", Version = "v1" });options.DocInclusionPredicate((docName, description) => true);//1.修改WebApiHost.xml生成路径,保证在发布的时候程序指向发布根目录的HPE_ProjectManagement_WebApi.Web.xml文件//2.发布站点时候,要把HPE_ProjectManagement_WebApi.Web.xml文件拷贝到发布目录中var basePath = AppContext.BaseDirectory;var xmlPath = Path.Combine(basePath, "HPE_ProjectManagement_WebApi.Web.xml");options.IncludeXmlComments(xmlPath);});#region 跨域配置实例services.AddCors(options =>{//hyt配置options.AddPolicy("defaultOrigins",builder =>{//前端配置axios.defaults.withCredentials = true传递session,后台跨域不能配置AllowAnyOrigin(),必须指定域名,同时需要加上.AllowCredentials()//builder.WithOrigins(new[] { "http://127.0.0.1:8010" }).AllowAnyMethod().AllowAnyHeader().AllowCredentials();//builder.WithOrigins(new[] { "http://39.101.209.199:8010" }).AllowAnyMethod().AllowAnyHeader().AllowCredentials();//builder.WithOrigins(new[] { "http://10.8.108.59:8010" }).AllowAnyMethod().AllowAnyHeader().AllowCredentials();builder.WithOrigins(new[] { "http://pmp.hpe.cn", "http://10.8.108.59", "http://127.0.0.1:8010", "https://pmp.hpe.cn" }).AllowAnyMethod().AllowAnyHeader().AllowCredentials();//builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();});// BEGIN01options.AddPolicy("AllowSpecificOrigins",builder =>{builder.WithOrigins("http://example.com", "http://www.contoso.com");});// END01// BEGIN02options.AddPolicy("AllowAllOrigins",builder =>{builder.AllowAnyOrigin();});// END02// BEGIN03options.AddPolicy("AllowSpecificMethods",builder =>{builder.WithOrigins("http://example.com").WithMethods("GET", "POST", "HEAD");});// END03// BEGIN04options.AddPolicy("AllowAllMethods",builder =>{builder.WithOrigins("http://example.com").AllowAnyMethod();});// END04// BEGIN05options.AddPolicy("AllowHeaders",builder =>{builder.WithOrigins("http://example.com").WithHeaders("accept", "content-type", "origin", "x-custom-header");});// END05// BEGIN06options.AddPolicy("AllowAllHeaders",builder =>{builder.WithOrigins("http://example.com").AllowAnyHeader();});// END06// BEGIN07options.AddPolicy("ExposeResponseHeaders",builder =>{builder.WithOrigins("http://example.com").WithExposedHeaders("x-custom-header");});// END07// BEGIN08options.AddPolicy("AllowCredentials",builder =>{builder.WithOrigins("http://example.com").AllowCredentials();});// END08// BEGIN09options.AddPolicy("SetPreflightExpiration",builder =>{builder.WithOrigins("http://example.com").SetPreflightMaxAge(TimeSpan.FromSeconds(2520));});// END09});#endregion//取消文件上传大小限制services.Configure<FormOptions>(x =>{x.ValueLengthLimit = int.MaxValue;x.MultipartBodyLengthLimit = int.MaxValue;x.MemoryBufferThreshold = int.MaxValue;});//Configure Abp and Dependency Injectionreturn services.AddAbp<HPE_ProjectManagement_WebApiWebModule>(options =>{//Configure Log4Net loggingoptions.IocManager.IocContainer.AddFacility<LoggingFacility>(f => f.UseAbpLog4Net().WithConfig(_hostingEnvironment.IsDevelopment()? "log4net.config": "log4net.Production.config"));});}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){//初始化ABpapp.UseAbp(); //Initializes ABP framework.if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Error");}// 使用已定义的跨域配置app.UseCors("defaultOrigins");// 使用swaggerapp.UseSwagger();app.UseSwaggerUI(c =>{c.SwaggerEndpoint("/swagger/v1/swagger.json", "项目管理平台 WebApi");});// 使用静态文件app.UseStaticFiles();// 使用sessionapp.UseSession();// .net6 路由app.UseRouting();//JWT身份认证 将身份验证中间件添加到管道中app.UseAuthentication();// .net6 终结点app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");});}}
}
2.1 automapper代码修改
- 由于使用automapper10.0所以提供的api有变化,CreateMap()改为静态方法。
- mapping配置文件修改如下
using AutoMapper;
using AutoMapper.Configuration;
using HPE_ProjectManagement_WebApi.Core;
using System;
using System.Collections.Generic;
using System.Text;
using HPE_ProjectManagement_WebApi.Utility;
using UserRole = HPE_ProjectManagement_WebApi.Core.UserRole;namespace HPE_ProjectManagement_WebApi.Application
{public class MappingProfile : Profile{public MappingProfile(){#region entity=>dto// commonCreateMap<Logger, LoggerDto>();CreateMap<Company, CompanyDto>();CreateMap<Company, CompanyOutputDto>();CreateMap<Expert, ExpertDto>();CreateMap<User, UserDto>().ForMember(dest => dest.Cellphone, opt => opt.MapFrom(src => src.Cellphone.Decrypt()));CreateMap<User, UserOutputDto>().ForMember(dest => dest.Cellphone, opt => opt.MapFrom(src => src.Cellphone.Decrypt()));CreateMap<Contract, ContractDto>();CreateMap<Contract, ContractOutputDto>();CreateMap<ComAttachment, ComAttachmentDto>();CreateMap<Dictionary, DictionaryDto>();CreateMap<Notification, NotificationDto>();}}
}
- 在base类中注入IMapper,方便业务代码调用
//BaseService
public readonly IRepository<T> _repository;
public readonly IRepository<Logger, long> _logger;
public readonly IMapper _mapper;
#region 构造函数
public BaseAppService(IRepository<T> repository)
{_repository = repository;
}
public BaseAppService(IRepository<T> repository, IMapper mapper)
{_repository = repository;_mapper = mapper;
}
public BaseAppService(IRepository<T> repository, IMapper mapper, IRepository<Logger, long> logger)
{_repository = repository;_mapper = mapper;_logger = logger;
}
//业务类
public class CompanyAppService : BaseAppService<Company, CompanyDto>, ICompanyAppService
{private readonly IRepository<ProjectCompany> _projectComanyRepository;private readonly ICompanyCategoryAppService _companyCategoryAppService;//[UnitOfWork]public CompanyAppService(IRepository<Company> repository,IMapper mapper,IRepository<Logger, long> logger,IRepository<ProjectCompany> projectComanyRepository,ICompanyCategoryAppService companyCategoryAppService) : base(repository, mapper, logger){_projectComanyRepository = projectComanyRepository;_companyCategoryAppService = companyCategoryAppService;}
}
3.项目启动错误排查
-
第一次启动的时候在执行到app.UseAbp()报错,错误如下:
-
错误指向的问题是automapper的问题,但是查了代码层面和项目引用的包都没有发现问题,最后网上找到解决方案,问题是出在两个项目的包版本不一致。
-
这里排查之后,在web项目中使用了包 AutoMapper.Extensions.Microsoft.DependencyInjection(11.0.0),里面包含 AutoMapper(11.0.0),然后在我们的Application项目中使用了包Abp.AutoMapper(7.3.0),里面包含AutoMapper(10.1.1),这里可以看到两个项目的automapper的版本是不一致,所以我们需要进行修改。
-
因为Abp.AutoMapper最新版本就是7.3.0,所以我们必须要将AutoMapper.Extensions.Microsoft.DependencyInjection的版本降为8.1.1来支持AutoMapper(10.1.1)。
-
所以这就是上面提到的自动更新包可能出现问题。
-
手动调整包版本后再次启动项目,这里没有出现automapper的问题,但是却一直没有成功直到超时。错误如下
-
首先是查看项目日志,因为项目没有启动成功所以没有具体错误,所以需要查看系统事件。
-
根据这个错误,网上查询,解决方案是需要在项目文件中添加下面节点
<PropertyGroup><Version>1.0.0.0</Version><TargetFramework>net6.0</TargetFramework> <AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback><PreserveCompilationContext>true</PreserveCompilationContext><AssemblyName>HPE_ProjectManagement_WebApi.Web</AssemblyName><OutputType>Exe</OutputType><PackageId>HPE_ProjectManagement_WebApi.Web</PackageId><GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles><AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects><GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType><AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel></PropertyGroup>
- 再次启动项目,成功打开。
4.其他
- 其他代码层面的问题,需要遇到后在具体分析。