Asp.NET Core 3.1 and Swashbuckle.AspNetCore.Swagger
After hours and hours digging I found that with Microsoft.OpenApi 1.2.0-preview isn't compactibile with .net core 3.1 and swagger v5, use v1.1.4 of Microsoft OpenApi
Wasyster
Updated on June 24, 2022Comments
-
Wasyster almost 2 years
I updated my asp.net core app to v3.1 and updated my Swagger form v5.04 rc to v5.0, and everything stopped to work. The API is working, but I can't generate swagger file, and I was able.
Here is my swagger configuration.
public static class SwaggerConfig { [Obsolete] public static void ConfigureSWAGGER(this IServiceCollection serviceColletion) { if (serviceColletion == null) { throw new ArgumentNullException(nameof(serviceColletion)); } // Use http://localhost:5000/swagger/ui/index to inspect API docs serviceColletion.AddSwaggerGen(x => { x.SwaggerDoc(Constatns.BackofficeSwaggerGroup, new OpenApiInfo { Title = "Portal Nekretnine - Backoffice", Version = Constatns.BackofficeSwaggerGroup }); x.SwaggerDoc(Constatns.PublicSwaggerGroup, new OpenApiInfo { Title = "Portal Nekretnine - Public", Version = Constatns.PublicSwaggerGroup }); // This code allow you to use XML-comments string xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; string xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); if (File.Exists(xmlPath)) { x.IncludeXmlComments(xmlPath); } x.AddSecurityDefinition ( "Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Please enter token into the field", Name = "Authorization", Type = SecuritySchemeType.ApiKey } ); }); } public static void UseSWAGGER(this IApplicationBuilder applicationBuilder) { // Enable middleware to serve generated Swagger as a JSON endpoint. applicationBuilder.UseSwagger(); // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), // specifying the Swagger JSON endpoint. applicationBuilder.UseSwaggerUI(x => { x.SwaggerEndpoint($"/swagger/{Constatns.BackofficeSwaggerGroup}/swagger.json", "Portal Nekretnine - Backoffice"); x.SwaggerEndpoint($"/swagger/{Constatns.PublicSwaggerGroup}/swagger.json", "Portal Nekretnine - Public"); }); } }
And this is my startup.cs
public partial class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration, IWebHostEnvironment env) { Configuration = configuration; if (env.IsDevelopment()) { IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile($"appsettings.development.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); } else { IConfigurationBuilder builder = new ConfigurationBuilder() .AddJsonFile($"appsettings.production.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); } } // This method gets called by the runtime. Use this method to add services to the container. [System.Obsolete] public void ConfigureServices(IServiceCollection services) { SetServices(services); services.ConfigureCOMPRESSION(); //disable built in model validator services.Configure<ApiBehaviorOptions>(options => { options.SuppressModelStateInvalidFilter = true; }); services.AddMvcCore(options => { //Validate model options.Filters.Add(typeof(ValidateModelAttribute)); // Add "Cache-Control" header options.Filters.Add(typeof(CacheControlFilter)); // Add custom binder provider for mapping json object form multipart/form-data options.ModelBinderProviders.Insert(0, new JsonModelBinderProvider()); }) .SetCompatibilityVersion(CompatibilityVersion.Version_3_0) .AddApiExplorer(); services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(); options.SerializerSettings.Converters.Add(new JsonDateConverter()); options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; #if DEBUG options.SerializerSettings.Formatting = Formatting.Indented; #else options.SerializerSettings.Formatting = Formatting.None; #endif }); services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); services.ConfigureCookieAuthentication(); services.ConfigureAUTH(Configuration); services.ConfigureCORS(); services.ConfigureSWAGGER(); services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen() } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseRouting(); app.UseCOMPRESSION(); app.UseAUTH(); app.UseAuthorization(); app.UseCORS(); app.UseSWAGGER(); app.UseHttpStatusCodeExceptionMiddleware(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
and an example of my controllers:
[ApiController] public class SecurityController : ControllerBase { [ApiExplorerSettings(GroupName = Constatns.PublicSwaggerGroup)] [SwaggerOperation(OperationId = "registerVisitor")] [HttpPost("api/register/visitor")] [ValidateModel] [AllowAnonymous] [ProducesResponseType((int)HttpResponseType.OK, Type = typeof(TokenResponse))] [ProducesResponseType((int)HttpResponseType.BadRequest)] [Produces("application/json")] public async Task<TokenResponse> RegisterVisitor([FromBody] RegisterVisitorRequest data) {} }
The error that I am getting are:
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1] An unhandled exception has occurred while executing the request. System.MissingMethodException: Method not found: 'Void Microsoft.OpenApi.Writers.OpenApiJsonWriter..ctor(System.IO.TextWriter)'. at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.RespondWithSwaggerJson(HttpResponse response, OpenApiDocument swagger) at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.RespondWithSwaggerJson(HttpResponse response, OpenApiDocument swagger) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
thnx