背景

我用了一个叫Unchase.Swashbuckle.AspNetCore.Extensions的库来加强Swagger的文档,我一般写法是这样的:

builder.Services.AddSwaggerGen(c =>
{
//文档
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "『xxx』后端接口:myapi",
Version = "v1"
});
c.SwaggerDoc("v2", new OpenApiInfo { Title = "v2", Version = "v2" });
c.MapType<long>(() => new OpenApiSchema { Type = "string" }); //获取注释
var apiXmlPath = Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml");
c.IncludeXmlComments(apiXmlPath); c.DescribeAllParametersInCamelCase();
c.AddEnumsWithValuesFixFilters(services, o =>
{
o.IncludeDescriptions = true;
o.IncludeXEnumRemarks = true;
o.DescriptionSource = DescriptionSources.DescriptionAttributesThenXmlComments;
o.IncludeXmlCommentsFrom(apiXmlPath);
});
}); ... var app = builder.Build(); // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
...

在.net core 3.1 和.net5 都运行好好的,在.net6就报异常:

InvalidOperationException: Cannot modify ServiceCollection after application is built.

System.InvalidOperationException: Cannot modify ServiceCollection after application is built.
at Microsoft.AspNetCore.WebApplicationServiceCollection.CheckServicesAccess()
at Microsoft.AspNetCore.WebApplicationServiceCollection.Add(ServiceDescriptor item)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton(IServiceCollection services, Type serviceType, Object implementationInstance)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton[TService](IServiceCollection services, TService implementationInstance)
at Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.Configure[TOptions](IServiceCollection services, String name, Action`1 configureOptions)
at Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions.Configure[TOptions](IServiceCollection services, Action`1 configureOptions)
at Unchase.Swashbuckle.AspNetCore.Extensions.Extensions.SwaggerGenOptionsExtensions.AddEnumsWithValuesFixFilters(SwaggerGenOptions swaggerGenOptions, IServiceCollection services, Action`1 configureOptions)
at WebApi6._0.Bootstrapper.<>c__DisplayClass0_0.<AddSwagger>b__0(SwaggerGenOptions c) in D:\learn\netcoreTest\WebApi6.0\Bootstrapper.cs:line 32
at Microsoft.Extensions.Options.ConfigureNamedOptions`1.Configure(String name, TOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.UnnamedOptionsManager`1.get_Value()
at Swashbuckle.AspNetCore.SwaggerGen.ConfigureSwaggerGeneratorOptions..ctor(IOptions`1 swaggerGenOptionsAccessor, IServiceProvider serviceProvider, IWebHostEnvironment hostingEnv)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.SwaggerGenServiceCollectionExtensions.<>c.<AddSwaggerGen>b__0_1(IServiceProvider s)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.GetService(IServiceProvider sp, Type type, Type middleware)
at lambda_method1(Closure , Object , HttpContext , IServiceProvider )
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass5_1.<UseMiddleware>b__2(HttpContext context)
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

下了源码下来发现,问题应该出现在这行:

...
c.AddEnumsWithValuesFixFilters(services, o =>
{
o.IncludeDescriptions = true;
o.IncludeXEnumRemarks = true;
o.DescriptionSource = DescriptionSources.DescriptionAttributesThenXmlComments;
o.IncludeXmlCommentsFrom(apiXmlPath);
});
...

对应nuget源码的这行:

   if (configureOptions != null)
{
services?.Configure(configureOptions);
}

https://github.com/unchase/Unchase.Swashbuckle.AspNetCore.Extensions/blob/d710cb6557944c49824d0cb31b72b90ad0319c1f/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/SwaggerGenOptionsExtensions.cs#L82

原因是:.net6之后已经不允许在

var app = builder.Build();

app build后再做 services?.Configure()操作

那简单;

解决

思路是,先在build操作之前就把services?.Configure()这种操作写好

所以我这里的写法可以改为:

1、先更换引用的nuget包(因为在作者修改这个问题前暂时打了一个自己的nuget)

<PackageReference Include="Unchase.Swashbuckle.AspNetCore.Extensions" Version="2.6.12" />

//改为
<PackageReference Include="Hei.Unchase.Swashbuckle.AspNetCore.Extensions" Version="2.6.12.1" />

2、上面代码改为:

var apiXmlPath = Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml");
//这里提前
var action = new Action<FixEnumsOptions>(o =>
{
o.IncludeDescriptions = true;
o.IncludeXEnumRemarks = true;
o.DescriptionSource = DescriptionSources.DescriptionAttributesThenXmlComments;
o.IncludeXmlCommentsFrom(apiXmlPath);
}); services.AddSwaggerGen(c =>
{
//文档
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "『xxx』后端接口:myapi",
Version = "v1",
});
c.SwaggerDoc("v2", new OpenApiInfo { Title = "v2", Version = "v2" });
c.SwaggerDoc("v3", new OpenApiInfo { Title = "v3", Version = "v3" });
c.SwaggerDoc("v4", new OpenApiInfo { Title = "华为服务号相关/健康币", Version = "v4" });
c.MapType<long>(() => new OpenApiSchema { Type = "string" });
c.IncludeXmlComments(apiXmlPath);
c.DescribeAllParametersInCamelCase();
//这里改为
c.AddEnumsWithValuesFixFilters(action);
});

问题解决!

总结

在同样.net6报这个错的时候注意看看:没页面先在build操作之前就把services?.Configure()这种操作写好

InvalidOperationException Cannot modify ServiceCollection after application is built .Net6 异常的更多相关文章

  1. webservice有关application/xop+xml的异常

    今天同事调用一个webservice时返回类似错误 响应消息的内容类型 multipart/related; type="application/xop+xml"; boundar ...

  2. idea application.properties图标显示异常(无小树叶)

    项目中(多级模块)如果没有主启动类时,新建的application.properties文件显示图标是文本格式图标,就如第一张图所示 添加该项目该模块下主启动类,就可以解决图标显示问题,也就可以看到可 ...

  3. MasaFramework的MinimalAPI设计

    在以前的MVC引用程序中,控制器负责接收输入信息.执行.编排操作并返回响应,它是一个功能齐全的框架,它提供了过滤器.内置了模型绑定与验证,并提供了很多可扩展的管道,但它偏重,不像其它语言是通过更加简洁 ...

  4. How to modify a compiled Android application (.apk file)

    Today I’d like to share with you my findings about how an existing .apk file can be modified. An .ap ...

  5. Understanding and Analyzing Application Crash Reports

    Introduction When an application crashes, a crash report is created and stored on the device. Crash ...

  6. [转]Creating an Entity Framework Data Model for an ASP.NET MVC Application (1 of 10)

    本文转自:http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/creating-a ...

  7. SilverLight抛出 System.InvalidOperationException: 超出了2083 的最大URI

    在SilverLight中对于抛出 System.InvalidOperationException: 超出了 2083 的最大 URI 长度 的异常 处理 其实很简单 在 EntityFramewo ...

  8. WPF入口Application

    1.WPF和 传统的WinForm 类似, WPF 同样需要一个 Application 来统领一些全局的行为和操作,并且每个 Domain (应用程序域)中只能有一个 Application 实例存 ...

  9. [转]WPF入口Application

    1.WPF和 传统的WinForm 类似, WPF 同样需要一个 Application 来统领一些全局的行为和操作,并且每个 Domain (应用程序域)中只能有一个 Application 实例存 ...

  10. Java性能提示(全)

    http://www.onjava.com/pub/a/onjava/2001/05/30/optimization.htmlComparing the performance of LinkedLi ...

随机推荐

  1. OpenTK 入门 初始化窗口

    本文属于 OpenTK 入门博客,这是一项使用 C# 做底层调用 OpenGL 和 OpenAL 和 OpenCL 的技术.但值得一提的是,如果是想做渲染相关的话,当前是不建议使用 OpenGL 的, ...

  2. dotnet SemanticKernel 入门 调用原生本机技能

    本文将告诉大家如何在 SemanticKernel 里面调用原生本机技能,所谓原生本机技能就是使用 C# 代码编写的原生本地逻辑技能,这里的技能可讲的可不是游戏角色里面的技能哈,指的是实现某个功能的技 ...

  3. 2018-8-10-使用-Resharper-快速做适配器

    title author date CreateTime categories 使用 Resharper 快速做适配器 lindexi 2018-08-10 19:16:51 +0800 2018-2 ...

  4. Apache Pulsar 桌面端图形化管理工具

    Apache Pulsar 桌面端图形化管理工具 Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息.存储.轻量化函数式计算为一体,采用计算与存储 ...

  5. Debian(WSL)安装gprMax教程 - 适用于Windows系统

    原文发布于:https://blog.zhaoxuan.site/archives/33.html: 第一时间获取最新文章请关注博客个人站:https://blog.zhaoxuan.site. 1. ...

  6. CSS样式第四篇

    ​针对现在网站的图片过大问题,可以用相应的工具进行压缩,并且可对图片进行切割处理. 1.如果一个页面的图片过大,可以对其切割,代码<img src="1.jpg">&l ...

  7. C数据结构:KMP算法详解(呕心沥血)

    KMP算法 作者心声 了解暴力求解(必需会) KMP算法详解 记住我这段话(你会爱上它的)← : ①前后缀及其用处 ②求出前后缀的next数组 求出next数组的代码 开始实现KMP算法 结尾 附上源 ...

  8. mysql-8.4.0解压版安装记录

    MySQL 8.4.0解压版安装记录 这几天,安装最新版mysql 8.4的时候,遇到了不少问题,网上的教程大多数都是旧版本的,也安装不成功. 参考了大量教程后,经过自己的摸索终于装好了,这里记录一下 ...

  9. MySQL所有的主从同步架构搭建方式

    目录 一.前言 二.关于MySQL主从同步 三.部署规划 3.1 服务器规划 3.2 数据库目录规划 四.准备工具 五.四台机器上使用通用二进制包安装MySQL(以node7为例) 5.1 上传MyS ...

  10. 【C#】预处理指令的学习 条件编译

    预处理指令,我的理解是,编译器在编译过程中所做的指令,能根据用户定义的条件选择性的编译代码. 比如在debug下要打印些信息,然而release之后,不能出现debug的信息,这个时候就能用预处理指令 ...