最全的 netcore 3.0 升级实战方案

1、哈喽大家中秋节(后)好呀!感觉已经好久没有写文章了,但是也没有偷懒哟,我的视频教程《系列一、NetCore 视频教程(Blog.Core)》也已经录制八期了,还在每周末同步更新中,欢迎大家多多指教。

2、除此之外呢,我也在平时的时间帮朋友开发了一个小项目,就是使用 .net mvc+vue+ele+mongo 框架写的项目,之前一直想着用mvc结合着vue写,这次也终于上手了,不过是一个小的demo,因为是朋友的项目,所以就不开源了。

言归正传,?  从2018年8月就开始听说 netcore 要准备3.0了,? 到了近期 v3.0.0-preview9 的发布,官方也最终定稿不会再更新了, ?  接着马上 在下周 9月23日至25日 .NET Conf 社区大会上,会正式推出 netcore3.0 版本, (最后 ? 微软会将 .netcore 和 .net 进一步融合,推出完美跨平台 net 5.0 版本,这里暂时先不说),单单从这一年里 netcore 3.0 的快速发展、迭代以及接受用户的反馈进一步修改中,我们就能感觉的到,微软是如何的有希望并且有信心在未来的发展中,将微软系产品进一步融入到广大开发者的心中,我们也要有信心微软能做到这一点。

在netcore 3.0 马上要到来之际,我也要尝尝鲜,我肯定不是第一个吃螃蟹的人,博客园这两个月也是一直轰轰烈烈的进行 3.0 的更新和迭代,不过过程是怎样的吧,至少结果目前还是可以的,也可以作为一个成功案例给大家提供一些建议和思路。

感觉尝试就是成功的一半,所以我在中秋节这两天,也把 Blog.Core  项目给提升到了 3.0 版本,大家现在看的我的在线地址(http://apk.neters.club/index.html) 就是netcore 3.0 的,总体看起来,可能没有什么差别,而且运行中也没有发现任何问题,(具体的请看我的后台项目:http://vueadmin.neters.club/),不过这次官方更新的东西还是稍微挺多的,所以我这里就统一做下记录,方便大家吧,希望每一个在使用 netcore 的小伙伴都能从这里得到一些帮助,虽然官网也有一些记录,但是我看了看,英文的可能有些小伙伴不好理解,尽管有中文翻译版,可是看着不是很通顺,而且也不是很全,大家可以看看:地址。

当然不仅仅包括下边的这几点,我还在慢慢更新,如果你使用到了我 blog.core 项目中没有用到的技术,并且自己在更新 3.0 的时候出现了问题,可以和我聊聊,我在下边补充下,争取达到一个最全的解决方案合集。

 640?wx_fmt=png

好啦,废话到此结束,马上开始今天的迁移报告内容!???

netcore 1.0 到 2.0 主要的是网络和云服务的升级,那 net core 从2.0 到 3.0 更新的是哪些呢?

这里我就简单的列举了下这一年来netcore 3.0 更新的比较热门的特性,当然还有其他的,因为本篇文章主要是讲解升级实战,所以对以下特性就不过多的铺开讲解。

性能、性能、性能,重要的地方说三遍

在机器学习,AI等很好的支持

对Winform、WPF的支持

gRPC的添加

支持 API 授权在单页面应用 (Spa) 中提供身份验证、实现 Open ID Connect 的IdentityServer结合。

Worker Service 模板,为开发做服务或监控微服务相关Bus

Microsoft.Data.SqlClient:独立存在于.NET Framework和.NET Core中

ReadyToRun

HttpClient支持HTTP/2

Json.NET 不在内置在框架内,使用System.Text.Json

HostBuilder 替换掉WebHostBuilder

Blazor 是一个用于使用 .NET 生成交互式客户端 Web UI 的框架,用c#开发前端

.NET Framework不支持.NET Standard 2.1

IL linker

发布成单个程序 dotnet publish -r win10-x64 /p:PublishSingleFile=true

那下面我就针对我的 Blog.Core 项目,坐下迁移的说明,一共八个方面,不是很多,大家可以一一对比下。

操作前必备:备份文件,这个很重要,我们要玩儿新花样,肯定要做好备份文件,可别因为升级失败,而不好回退。

当然我的操作是直接操作的 Blog.Core 项目,因为项目在 git 上,如果不成功,就直接回退,这种资源管理工具还是很有必要的。

1、安装SDK

 首先可以查看自己的本地 SDK 是什么版本的,比如我的目前只有 2.1和 2.2 :

640?wx_fmt=png

所以,如果我们要升级 3.0 的话,就肯定要安装指定的 SDK 了,下载地址:https://dotnet.microsoft.com/download/visual-studio-sdks

选择指定版本的 SDK ,然后进行安装,最后我们就可以看到我们的本地已经安装好了:

640?wx_fmt=png

 这里我们可以看到我们的 3.0 的 SDK 已经安装好了,最后再做个验证,就是在我们的 VS 2019 中,查看是否有 3.0 的框架:

640?wx_fmt=png

竟然没有??!!别慌,这里有两个方法:

1、工具 -> 选项 -> 项目与解决方案 -> 右侧,勾选预览版(这个方案是2019 最旧版本的,已取消请忽略)。

640?wx_fmt=png

2、在工具 -> 选项 -> 环境里(正规是使用这个):

640?wx_fmt=png

然后我们把 vs 重新启动一下,发现已经有了:

640?wx_fmt=png

安装好了 SDK,我们就已经是成功了一半了,下边我们就正式开始升级打怪之路。

但是这里还有一个问题,就是打开的项目属性里,虽然有了 3.0 的框架,但是新建的项目,依然没有 3.0 的部分,那这个是为什么呢?

640?wx_fmt=png

这里网上的方案是:不要用preview8或者9,这两个版本出不来core3.0的选项,preview7没有问题。如果非要用最新版,可以用dotnet new创建项目,或者等下星期的 net core 3.0正式版出来,这样就不用来来回回勾选了。

Tips:感谢 @ 给出建议

https://dotnet.microsoft.com/download/dotnet-core/3.0
这个页面的Tips已经说了,有可能下周就是Core3.0和VS 2019的16.3一起发布,猜测应该就是更新就行了,目前我的VS版本是16.2.5

2、更新框架以及所有依赖

刚刚我们已经成功的安装好了 3.0 的 SDK ,那接下来就是正式开始升级项目,首先呢,就是需要更新我们的目标框架,这里有两种方法:

第一种是直接修改我们的项目文件 .csproj ,修改节点 <TargetFramework>netcoreapp3.0</TargetFramework>,并移除关于 Aspnetcore 2.2 相关的包;

第二种就是直接右键项目,属性,应用程序,修改目标框架到 netcore 3.0 就行,就是上文截图中显示的那个,我个人采用的是这种方法。

640?wx_fmt=png

记得要把项目从底层开始更新,比如从 Model 层和 Common 层开始更新,然后最后更新 API 层,就是从下向上,(这里有个小问题,就是出现修改了,CTRL S 保存后,又重新回到2.2了,可以重启下项目,重启下vs就行了)。

代码修改对比图:

640?wx_fmt=png

(netcore 3.0 修改sdk框架)

 接下来,就是把项目中用到的所有nuget包都更新到最新的版本,因为有些是为了迎接 netcore 3.0,做了相应的修改,比如下午说到的 swagger ,一定要更新到 5.0+版本。

 到了这里,我们的项目已经把框架和依赖升级完成了,是不是很简单,重新编译,运行,这里肯定会有错误,别着急,接下来我们就进一步修改 Code 中出现的bug。 

3、宿主机变化(Program.cs)

netcore 3.0,对 host 做了调整,底层没有发生太多的变化,这里不细说,主要说要修改的地方,更新的内容,我会在视频里,详细给大家讲解。

在 Program.cs 文件中,修改HostBuilder生成方法,注意在main 方法里引用也要做相应的修改

代码修改对比图:

640?wx_fmt=png

 (Program.cs 修改 host 宿主机)

CODE:

 public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseStartup<Startup>()
.UseUrls("http://localhost:8081")
//这里是配置log的
.ConfigureLogging((hostingContext, builder) =>
{
builder.ClearProviders();
builder.SetMinimumLevel(LogLevel.Trace);
builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
builder.AddConsole();
builder.AddDebug();
});
});

4、Host 环境变量(Startup.cs)

从上边我们也可以看得出来,官方更新了 host ,所以自然而然的,也更新了部分的命名空间,这样就出现了一个问题:

当 Microsoft.Extensions.Hosting 在 2.1 中被引入时,某些类型 IHostingEnvironment 和 IApplicationLifetime 是从 Microsoft.AspNetCore.Hosting 复制的。某些 3.0 更改会导致应用同时包含 Microsoft.Extensions.Hosting 和 Microsoft.AspNetCore.Hosting 两个命名空间。当同时引用两个命名空间时,对这些重复类型的任何使用都会导致"不明确的引用"编译器错误。

所以官方就对某些命名空间和类做了修改:

Obsolete types (warning):

Microsoft.Extensions.Hosting.IHostingEnvironment
Microsoft.AspNetCore.Hosting.IHostingEnvironment
Microsoft.Extensions.Hosting.IApplicationLifetime
Microsoft.AspNetCore.Hosting.IApplicationLifetime
Microsoft.Extensions.Hosting.EnvironmentName
Microsoft.AspNetCore.Hosting.EnvironmentName

New types:

Microsoft.Extensions.Hosting.IHostEnvironment
Microsoft.AspNetCore.Hosting.IWebHostEnvironment : IHostEnvironment
Microsoft.Extensions.Hosting.IHostApplicationLifetime
Microsoft.Extensions.Hosting.Environments

这个不用记忆,到时候使用的时候,会有提示的,那我们的项目中,有哪个地方需要修改呢,就是配置中间件的时候有一个环境变量配置需要修改下:

1、将 IHostingEnvironment env 改成 IWebHostEnvironment env,这个时候会报错,因为命名空间变了;

2、所以需要引用新的命名空间:using Microsoft.Extensions.Hosting;

到了这里,我们就完全修改好了宿主机的部分,现在项目还不能正常的使用,还需要继续修改 mvc 部分,别着急,慢慢往下看。


刚刚我们修改了宿主机 host ,启动项目的时候,还是会有错误,主要提示我们的中间件 .UseMvc() 已经不能被使用了,3.0后,对mvc做了较大的修改,主要从两个方面,一个是服务注册,一个是中间件的拆分:

1、MVC 服务注册(Startup.cs)

在 netcore 3.0 中,官方对 mvc 服务做了细分,主要有以下几个部分:

  services.AddMvc();// 我们平时2.2使用的,最全面的mvc服务注册
services.AddMvcCore();// 稍微精简的mvc注册
services.AddControllers();// 适用于api的mvc部分服务注册
services.AddControllersWithViews();//含有api和view的部分服务注册
services.AddRazorPages();//razor服务注册

我们看出来,如果我们的项目是webapi的,那只需要注册 .AddControllers() 这个就够了,.AddMvc() 里边服务太多,会造成浪费,而大材小用。

代码修改对比图:

640?wx_fmt=png

2、MVC 中间件的拆分(Startup.cs)

除了上边的 mvc 服务注册以外,我们还需要对 UseMvc() 中间件做修改。

官方已经正式去掉了Mvc()这个短路中间件,取代他的是 .UseEndpoints() 方法,我们可以做以下修改:

代码修改对比图:

640?wx_fmt=png

CODE:

 app.UseRouting();//路由中间件
// 短路中间件,配置Controller路由
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

到了这里,我们已经完成了 netcore 2.2 到 net core 3.0 的最简单的升级,如果你想尝试下,可以自己手动建立一个空的 2.2 项目,实现到 3.0 的迁移,我们运行项目,可以看到已经成功的启动起来,还是很成功的。这里要注意下中间件的顺序,一般的顺序是这样的:

  app.UseStaticFiles();

app.UseRouting();

app.UseCors();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chat");
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

那是不是到了这里已经完成了呢,答案当然是否定的,我们的项目不可能这么简单,肯定还会有其他的依赖,还有各种各样的中间件,那我们在升级的过程中,还会有哪些地方需要做处理呢,就比如下边的这些。

在 netcore 3.0 中,要求我们使用的是 swagger 5.0 ,而且变化的内容也挺多的,但是原理和思路都是一样的,大家一看就知道了,所以我就直接贴代码了。

1、代码修改对比图(ConfigureServices)

 这次的修改,主要是服务的注册部分,中间件没有变化,所以我们直接在 startup.cs 中的 configureService 中,做下调整:

这里要注意下,需要引用两个 Nuget 包:Swashbuckle.AspNetCore 和 Swashbuckle.AspNetCore.Filters

640?wx_fmt=png

2、修改后的完整代码

services.AddSwaggerGen(c =>
{
typeof(ApiVersions).GetEnumNames().ToList().ForEach(version =>
{
// swagger文档配置
c.SwaggerDoc(version, new OpenApiInfo
{
Version = version,
Title = $"{ApiName} 接口文档",
Description = $"{ApiName} HTTP API " + version,
Contact = new OpenApiContact { Name = ApiName, Email = "Blog.Core@xxx.com", Url = new Uri("https://www.jianshu.com/u/94102b59cc2a") },
License = new OpenApiLicense { Name = ApiName, Url = new Uri("https://www.jianshu.com/u/94102b59cc2a") }
});
// 接口排序
c.OrderActionsBy(o => o.RelativePath);
});

// 配置 xml 文档
var xmlPath = Path.Combine(basePath, "Blog.Core.xml");
c.IncludeXmlComments(xmlPath, true);
var xmlModelPath = Path.Combine(basePath, "Blog.Core.Model.xml");
c.IncludeXmlComments(xmlModelPath);

c.OperationFilter<AddResponseHeadersFilter>();
c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
// 很重要!这里配置安全校验,和之前的版本不一样
c.OperationFilter<SecurityRequirementsOperationFilter>();

// 开启 oauth2 安全描述
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
});

代码中,变化比较大的地方,我已经用红色标注,某些又做了注解,不过大部分的内容还是和之前是一样的,相信大家都能看得懂。

 关于依赖注入框架 Autofac 的变化,整体来说不是很大,主要是在依赖容器的使用上,在 2.2 的时候,我们是直接修改的的 ConfigureServices ,然后将容器实例给 return 出去,但是 3.0 之后,ConfigureServices 不能是返回类型了,只能是 void 方法,那我们就不用 return 出去了,官方给我们提供了一个服务提供上工厂,我们从这个工厂里拿,而不是将服务配置 return 出去。

1、代码修改对比图

 1、首先我们需要在 Program.cs 中的 CreateHostBuilder 中,添加Autofac的服务工厂:

640?wx_fmt=png

2、然后在 startup.cs 文件中,新建一个 ConfigureContainer(ContainerBuilder builder) 的方法,里边的内容就是我们之前写的 Autofac 的代码,把之前在 configureService 中的代码都删掉。

只不过我们这里是注入了 builder 的实例对象,不用new了,然后也不用 build 容器了,交给了 hotst 帮助我们一起 build。

640?wx_fmt=png

如果有任何看不懂的,请查看我的 Blog.Core 项目中的代码。

2、修改后的完整代码

 Startup.cs 中,新增 ConfigureContainer 方法,删除 ConfigureService中,所有有关 Autofac 的内容:

     public void ConfigureContainer(ContainerBuilder builder)
{
var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;

//注册要通过反射创建的组件
//builder.RegisterType<AdvertisementServices>().As<IAdvertisementServices>();
builder.RegisterType<BlogCacheAOP>();//可以直接替换其他拦截器
builder.RegisterType<BlogRedisCacheAOP>();//可以直接替换其他拦截器
builder.RegisterType<BlogLogAOP>();//这样可以注入第二个

// ※※★※※ 如果你是第一次下载项目,请先F6编译,然后再F5执行,※※★※※

#region 带有接口层的服务注入

#region Service.dll 注入,有对应接口
//获取项目绝对路径,请注意,这个是实现类的dll文件,不是接口 IService.dll ,注入容器当然是Activatore
try
{
var servicesDllFile = Path.Combine(basePath, "Blog.Core.Services.dll");
var assemblysServices = Assembly.LoadFrom(servicesDllFile);//直接采用加载文件的方法 ※※★※※ 如果你是第一次下载项目,请先F6编译,然后再F5执行,※※★※※

//builder.RegisterAssemblyTypes(assemblysServices).AsImplementedInterfaces();//指定已扫描程序集中的类型注册为提供所有其实现的接口。


// AOP 开关,如果想要打开指定的功能,只需要在 appsettigns.json 对应对应 true 就行。
var cacheType = new List<Type>();
if (Appsettings.app(new string[] { "AppSettings", "RedisCachingAOP", "Enabled" }).ObjToBool())
{
cacheType.Add(typeof(BlogRedisCacheAOP));
}
if (Appsettings.app(new string[] { "AppSettings", "MemoryCachingAOP", "Enabled" }).ObjToBool())
{
cacheType.Add(typeof(BlogCacheAOP));
}
if (Appsettings.app(new string[] { "AppSettings", "LogAOP", "Enabled" }).ObjToBool())
{
cacheType.Add(typeof(BlogLogAOP));
}

builder.RegisterAssemblyTypes(assemblysServices)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.EnableInterfaceInterceptors()//引用Autofac.Extras.DynamicProxy;
// 如果你想注入两个,就这么写 InterceptedBy(typeof(BlogCacheAOP), typeof(BlogLogAOP));
// 如果想使用Redis缓存,请必须开启 redis 服务,端口号我的是6319,如果不一样还是无效,否则请使用memory缓存 BlogCacheAOP
.InterceptedBy(cacheType.ToArray());//允许将拦截器服务的列表分配给注册。
#endregion

#region Repository.dll 注入,有对应接口
var repositoryDllFile = Path.Combine(basePath, "Blog.Core.Repository.dll");
var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
builder.RegisterAssemblyTypes(assemblysRepository).AsImplementedInterfaces();
}
catch (Exception ex)
{
throw new Exception("※※★※※ 如果你是第一次下载项目,请先对整个解决方案dotnet build(F6编译),然后再对api层 dotnet run(F5执行),\n因为解耦了,如果你是发布的模式,请检查bin文件夹是否存在Repository.dll和service.dll ※※★※※" + ex.Message + "\n" + ex.InnerException);
}
#endregion
#endregion


#region 没有接口层的服务层注入

////因为没有接口层,所以不能实现解耦,只能用 Load 方法。
////注意如果使用没有接口的服务,并想对其使用 AOP 拦截,就必须设置为虚方法
////var assemblysServicesNoInterfaces = Assembly.Load("Blog.Core.Services");
////builder.RegisterAssemblyTypes(assemblysServicesNoInterfaces);

#endregion

#region 没有接口的单独类 class 注入
////只能注入该类中的虚方法
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Love)))
.EnableClassInterceptors()
.InterceptedBy(typeof(BlogLogAOP));

#endregion

//这里不要再 build 了
//var ApplicationContainer = builder.Build();

}

program.cs

 public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) //<--NOTE THIS
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseStartup<Startup>()
.UseUrls("http://localhost:8081")
.ConfigureLogging((hostingContext, builder) =>
{
builder.ClearProviders();
builder.SetMinimumLevel(LogLevel.Trace);
builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
builder.AddConsole();
builder.AddDebug();
});
});

3、变化的核心点

就是将我们的Autofac的容器,从 configureService 中,转向了我们的宿主机中了,步骤是:

1、删除 ConfigureService 中的所有 Autofac 配置内容;

2、将刚刚删除的配置内容,拷贝到新建一个 ConfigureContainer  方法中;

3、在 ConfigureContainer 方法中,不要进行 build 操作,然后 Main 入口方法中的 Build() 去执行。

4、在 Program.cs 的 CreateHostBuilder 中,新增服务工厂实例。

好了,到现在,我们可以尝试看看 Autofac 依赖注入框架,已经可以正常的使用了。

随着netcore 3.0 的更新,sqlsugar当然也要做相应的优化处理,主要是为了配合 3.0 做处理,作者凯旋兄还是很负责的,及时做了调整,目前 sqlsugar 的版本是 5.0.9 ,我们如果使用 netcore 3.0 的话,就必须要使用。

1、这个 5.0.9 的版本,如果不使用的话,可能会有一个映射错误:

640?wx_fmt=png

 如果遇到了这个错误,直接不要问,更新到最新版本就行。

2、如果更新了以后,发现还有错误,一个《未将对象引用到对象的实例》:

640?wx_fmt=png

这个时候,你可以尝试重新生成下数据库,好像只需要创建下表结构就行,数据可以导入,记得做好生产环境数据库备份

其他还没有发现什么问题。

这一块我也发现有点儿问题,好像目前在controller 上配置 [Authorize(Policy = Permissions.Name)] 并不能实现授权的目的,就算是用官网的在短路节点配置也不行, .RequireAuthorization(new AuthorizeAttribute() { Policy = Permissions.Name, });,所以,起作用的还是我的授权公约过滤器,并不是加的特性,我还在调试,如果你正好写到 netcore 3.0 授权策略了,请评论,不胜感激。

这个地方其实很简单,刚刚在将 swagger 的时候,我也说到了,有一个地方需要我们注意, 就是安全校验的配置上,现在发生了变化,从服务添加变成了过滤器:

640?wx_fmt=png

之前我的 Blog.Core 项目使用了权限过滤器公约,这样就算 controller 没有配置 Authorize 的话,也会默认采用这种权限过滤器,

但是现在不行了,必须要在每一个 controller 上配置,才能在 swagger 中出现那个 小锁 的标志,所以我又都在 controller 上,加上了 [Authorize(Permissions.Name)]

如果不配置的话,是没有小锁标志,也就不会启动权限认证的作用的,只有配置了的才有,不仅如此,大家也可以看到,在左侧已经把该接口对应的权限也写上了:
640?wx_fmt=png

 在netcore 3.0 中,它内置了一个 json 工具—— System.Text.Json,而作为改善 ASP.NET Core 共享框架的工作的一部分,已从 ASP.NET Core 共享框架中删除Json.NET 。如果你的应用程序使用Newtonsoft.Json特定的功能(如 JsonPatch 或转换器),或者如果它是特定于格式 Newtonsoft.Json的类型,那我们就需要重新引用它。

简单来说,就是 3.0 内置了 Text.Json 框架,你可以直接使用,但是我没有用这个,因为我好像中间出现了一个序列化错误,而且我还要取消默认的驼峰命名,所以我还是采用的之前的 Newtonsoft.json,具体的使用方法请看:

1、如果使用 .net core 3.0 内置的 System.Text.Json ,配置方法如下:

services.AddMvc().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});

2、如果使用 Newtonsoft.Json ,配置方法如下:

services.AddControllers()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver = new DefaultContractResolver());

这个很简单,官方中间件取消了  UseSignalR 中间件,而放到了  UseEndpoints 短路中间件中,配置如下:

 app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/api2/chatHub");

endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

 CORS变化其实不大,整体来说和 2.2 一样的,具体的按照 之前的写法来写就行。

只是已经不支持向所有域名开放了,所以下边的 Policy 可以删除了,其他的不用变化:

  c.AddPolicy("AllRequests", policy =>
{
policy
.AllowAnyOrigin()//允许任何源
.AllowAnyMethod()//允许任何方式
.AllowAnyHeader()//允许任何头
.AllowCredentials();//允许cookie
});

然后就是要注意中间件的顺序,这里记得还要带上 policy 的名称 ,还是 app.UseCors("LimitRequests");:

640?wx_fmt=png

其他补充中

如果你有其他的用到的,是我没有使用到的, 或者我上文没有提到的注意点,

欢迎想问提问和反馈,我会在这里,给你署名写上,让更多的小伙伴可以学会学号。

谢谢。

https://github.com/anjoy8/Blog.Core

https://gitee.com/laozhangIsPhi/Blog.Core

app.UseStaticFiles(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapHub<ChatHub>("/chat"); endpoints.MapControllerRoute("default""{controller=Home}/{action=Index}/{id?}"); });

相关文章:

原文链接:https://www.cnblogs.com/laozhang-is-phi/p/11520048.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微软发布.Net Core 3.0 RC1,最终版本定于9月23日

2019.9.17 微软 宣布推出.NET Core 3.0 Release Candidate 1。就像Preview 9一样&#xff0c;主要专注于为 .NET Core 3.0 发布最终版本 。现在变得非常非常接近。将在9月23日.NET Conf上发布最终版本。.NET Core 3.0是从仅支持Windows传统的 .NET框架向更现代化的开源实现过渡…

JVM内存结构 VS Java内存模型 VS Java对象模型

Java作为一种面向对象的&#xff0c;跨平台语言&#xff0c;其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似&#xff0c;很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模型和Java对象模型&#xff0c;这就是三个截然不同的概念&…

迫于误解压力,RMS从自由软件基金会与MIT离职

自由软件基金会官网显示&#xff0c;基金会创始人兼主席、自由软件运动发起人 Richard M. Stallman&#xff08;RMS&#xff09;辞去主席职务并辞去董事会职务。而另一边&#xff0c;stallman.org 邮件列表显示&#xff0c;RMS 已经从麻省理工学院&#xff08;MIT&#xff09;计…

让人迷茫的三十岁!从专业技能、行业知识和软实力谈一下!

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区合伙人&#xff01;我今年三十岁&#xff0c;我很迷茫&#xff0c;不知道未来该选择什么发展方向。这是我无意中在社区微信群中看到的一位年轻的开发者说的话&#xff0c;之前他也经常会在技术群…

误用.Net Redis客户端工具CSRedisCore,自己挖坑自己填

前导  上次Redis MQ分布式改造完成之后&#xff0c; 编排的容器稳定运行了一个多月&#xff0c;昨天突然收到ETL端同事通知&#xff0c;没有采集到解析日志了。赶紧进服务器看了一下&#xff0c;用于数据接收的receiver容器挂掉了&#xff0c; 尝试docker container start [c…

Java——类加载机制

** 一、什么是类的加载 ** 类的加载指的是将类的.class文件中的二进制数据读入到内存中&#xff0c;将其放在运行时数据区的方法区内&#xff0c;然后在堆区创建一个java.lang.Class对象&#xff0c;用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class…

.NET中国峰会议题征集

月初做的调查《》&#xff0c;参与人数576人&#xff0c;愿意参与分享.NET Core经验的142人&#xff0c;今天发起分会场主题演讲和闪电演讲议题.2014年微软组织成立.NET基金会&#xff0c;微软在成为主要的开源参与者的道路上又前进了一步。2014年以来已经有众多知名公司加入.N…

一些学习教程资料等你来拿

近期整理自己的云盘中发现近年来私藏了很多学习资料和教程&#xff0c;本着独乐乐不如众乐乐的精神&#xff0c;特将其分享出来供有兴趣的童鞋学习。进入公众号&#xff0c;输入关键词"敏捷"/"agile"/"scrum"&#xff0c;即可获得敏捷开发类别的…

Java——编译与反编译

** 一、基础知识 ** 1.1 编程语言 在介绍编译和反编译之前&#xff0c;我们先来简单介绍下编程语言&#xff08;Programming Language&#xff09;。编程语言&#xff08;Programming Language&#xff09;分为低级语言&#xff08;Low-level Language&#xff09;和高级语…

程序员自家种水果,新鲜包邮配送

上次猕猴桃的活动<好多小伙伴&#xff0c;买了一箱尝过后又下单了好几箱。事实证明&#xff0c;品质才是销量的最佳保证。有些粉丝找到我说&#xff0c;自己家也有果园自己种水果&#xff0c;都是当天采摘当天发货的纯天然水果。于是他们给我寄了一些自家种的苹果、香瓜、冬…

【招聘(广州)】-年薪30W起-自助打印领域业内第一

印萌是一家为高校打印店提供整套“无人自助打印”解决方案的互联网科技公司&#xff0c;已获得数百万元融资&#xff0c;公司正向盈利。目前产品覆盖清华大学、北京大学、中山大学、复旦大学、浙江大学等700多所高校&#xff0c;多达1800间打印店&#xff0c;累计为全国1200万大…

尾递归

1、递归 简单的来说递归就是一个函数直接或间接地调用自身&#xff0c;是为直接或间接递归。一般来说&#xff0c;递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时&#xff0c;递归前进&#xff1b;当边界条件满足时&#xff0c;递归返回。 用递归需要注意以…

多场景抢红包业务引发.NETCore下使用适配器模式实现业务接口分离

事情的起因我们公司现有一块业务叫做抢红包&#xff0c;最初的想法只是实现了一个初代版本&#xff0c;就是给指定的好友单发红包&#xff0c;随着业务的发展&#xff0c;发红包和抢红包的场景也越来越多&#xff0c;目前主要应用的场景有&#xff1a;单聊发红包、群聊发红包、…

设计模式——创建型模型

目录 单例模式&#xff08;singleton&#xff09;构建模式&#xff08;Builder&#xff09;原型模式&#xff08;Prototype&#xff09;工厂方法模式&#xff08;Factory&#xff09;抽象工厂模式&#xff08;Abstract Factory&#xff09; ** 一、5种创建型模型 ** 1.1 单…

【C】KoobooJson在asp.net core中的使用

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。本文链接&#xff1a;https://blog.csdn.net/j_teng/article/details/100924973“KoobooJson是一款体积小巧没有任何依赖且性能表现强劲的Json工具…

【DevOps进行时】C/S端界面自动化测试:微软UIAutomation实践

在界面自动化测试领域里存在许多流行的自动化测试工具&#xff0c;例如目前比较受欢迎的开源自动化工具Selenium、Katalon&#xff1b;HP旗下知名的商业软件Unified Functional Testing(更名前叫QTP)&#xff1b;隶属于IBM以数据驱动测试的RTF&#xff08;Rational Functional …

代码编辑器横评:为什么 VS Code 能拔得头筹

2015 年 4 月 29 日的 Build 大会上&#xff0c;微软发布了 Visual Studio Code 第一个预览版本。短短四年时间里&#xff0c;VS Code 高速成长。根据 2019 年 2 月的 PYPL Top IDE index 的排名&#xff0c;VS Code 的涨势迅猛&#xff0c;在所有编辑器与 IDE 中排名第六&…

设计模式——结构型模型

一&#xff1a;目录 1. 装饰者模式&#xff08;Decorator&#xff09; 2. 代理模式&#xff08;Proxy&#xff09; 3. 组合模式&#xff08;Composite&#xff09; 4. 桥接模式&#xff08;Bridge&#xff09; 5. 适配器模式&#xff08;Adapter&#xff09; 6. 蝇量模式&#…

利用Helm简化Kubernetes应用部署(1)

目录利用Helm简化Kubernetes应用部署 Helm基础 安装Helm 使用Visual Studio 2019为Helm编写一个简单的应用 利用Helm简化Kubernetes应用部署Helm是Kubernetes生态系统中的一个软件包管理工具&#xff0c;有点类似于Linux操作系统里面的“apt-get”和“yum”。结合上一节内容&am…

设计模式——行为型模式

一&#xff1a;目录 1. 策略模式&#xff08;Strategy&#xff09; 2.状态模式&#xff08;State&#xff09; 3.责任链模式&#xff08;Chain Of Responsibility&#xff09; 4.解释器模式&#xff08;Interpreter&#xff09; 5.命令模式&#xff08;Command&#xff09; 6.观…