How can I help Swagger find its documentation? I have read multiple posts about Swagger documentation. Basically, my problem is that I can get Swagger to work on local host, but I cannot get Swagger to work once our API is deployed to our servers, and when I try to make Swagger work on development, test, and production servers, I break it on local host.
Here is the code in my Startup.cs when Swagger works on local host.
public void ConfigureServices(IServiceCollection services)
{
services
.AddCors()
.AddDbContext<OurDbContext1>(options =>
options.UseSqlServer(Configuration["ConnectionStrings:OurDatabase1"]))
.AddDbContext<OurDbContext2>(options =>
options.UseSqlServer(Configuration["ConnectionStrings:OurDatabase2"]))
.AddRazorPages()
.ConfigureApiBehaviorOptions(setupAction =>
{
setupAction.InvalidModelStateResponseFactory = context =>
{
var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Title = "One or more model validation errors occurred",
Status = StatusCodes.Status422UnprocessableEntity,
Detail = "See the errors property for details",
Instance = context.HttpContext.Request.Path
};
problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);
return new UnprocessableEntityObjectResult(problemDetails)
{
ContentTypes = { "application/problem+json" }
};
};
});
services
.AddMvc(options => options.EnableEndpointRouting = false)
.AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
services
.AddControllersWithViews();
services
.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services
.AddSwaggerGen(setupAction =>
{
setupAction.SwaggerDoc("OurApiSpecification", new OpenApiInfo()
{
Title = "Our API",
Version = "1"
});
setupAction.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
});
services
.AddScoped<IRepository1, Repository1>()
.AddScoped<IRepository2, Repository2>()
.AddTransient<IPropertyMappingService, PropertyMappingService>()
.AddTransient<IPropertyCheckingService, PropertyCheckingService>();
services
.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
if (_env.IsDevelopment())
{
services.AddSingleton<IPolicyEvaluator, DisableAuthenticationPolicyEvaluator>();
}
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
string[] allowedOrigins = Configuration.GetSection("CorsSettings:AllowedOrigins").Get<string[]>();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHsts();
app.UseCors(
options => options
.WithOrigins(
allowedOrigins
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
if (!env.IsDevelopment())
{
app.UseAuthentication();
}
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI(setupAction =>
{
setupAction.SwaggerEndpoint(
"/swagger/OurApiSpecification/swagger.json",
"Our API");
});
app.UseMvc();
}
However, when I deploy our API to the servers and try to access it at our URLs, I see the Fetch error Not Found /swagger/OurApiSpecification/swagger.json, which makes sense, because the API on the server exists at a different host name and path than it does locally.
The JSON documentation exists on the server at serverhostname/apifolder/ourapi/swagger/OurApiSpecification/swagger.json, but the error tells me that it is not found at the location specified in the Startup.cs, which, again, makes sense, since the documentation is not at /swagger/OurApiSpecification/swagger.json, but it is at /apifolder/ourapi/swagger/OurApiSpecification/swagger.json.
Therefore, after extensive research, I changed Startup.Configure() in an attempt to reference the Swagger JSON document at its location on the server, and, for good measure, in Startup.ConfigureServices(), I threw in SwaggerGen Newtonsoft support, but now Swagger will not work on localhost!
Now, here is the code in my Startup.cs when Swagger does not work on localhost.
public void ConfigureServices(IServiceCollection services)
{
services
.AddCors()
.AddDbContext<OurDbContext1>(options =>
options.UseSqlServer(Configuration["ConnectionStrings:OurDatabase1"]))
.AddDbContext<OurDbContext2>(options =>
options.UseSqlServer(Configuration["ConnectionStrings:OurDatabase2"]))
.AddRazorPages()
.ConfigureApiBehaviorOptions(setupAction =>
{
setupAction.InvalidModelStateResponseFactory = context =>
{
var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Title = "One or more model validation errors occurred",
Status = StatusCodes.Status422UnprocessableEntity,
Detail = "See the errors property for details",
Instance = context.HttpContext.Request.Path
};
problemDetails.Extensions.Add("traceId", context.HttpContext.TraceIdentifier);
return new UnprocessableEntityObjectResult(problemDetails)
{
ContentTypes = { "application/problem+json" }
};
};
});
services
.AddMvc(options => options.EnableEndpointRouting = false)
.AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
services
.AddControllersWithViews();
services
.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services
.AddSwaggerGen(setupAction =>
{
setupAction.SwaggerDoc("OurApiSpecification", new OpenApiInfo()
{
Title = "Our API",
Version = "1"
});
setupAction.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
});
services
.AddSwaggerGenNewtonsoftSupport();
services
.AddScoped<IRepository1, Repository1>()
.AddScoped<IRepository2, Repository2>()
.AddTransient<IPropertyMappingService, PropertyMappingService>()
.AddTransient<IPropertyCheckingService, PropertyCheckingService>();
services
.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
if (_env.IsDevelopment())
{
services.AddSingleton<IPolicyEvaluator, DisableAuthenticationPolicyEvaluator>();
}
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
string[] allowedOrigins = Configuration.GetSection("CorsSettings:AllowedOrigins").Get<string[]>();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHsts();
app.UseCors(
options => options
.WithOrigins(
allowedOrigins
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
if (!env.IsDevelopment())
{
app.UseAuthentication();
}
app.UseAuthorization();
app.UseSwagger(setupAction =>
{
setupAction.RouteTemplate =
"apifolder/ourapi/swagger/OurApiSpecification/swagger.json";
});
app.UseSwaggerUI(setupAction =>
{
setupAction.SwaggerEndpoint(
"/apifolder/ourapi/swagger/OurApiSpecification/swagger.json",
"Our API");
setupAction.RoutePrefix = "apifolder/ourapi/swagger";
});
app.UseMvc();
}
Again, it seems to make sense that the JSON documentation is not found, because, locally, the documentation is not at localhost/apifolder/ourapi/swagger/OurApiSpecification/swagger.json. I verified this, BUT I don't know why it is not at /apifolder/ourapi/swagger/OurApiSpecification/swagger.json, because it should be there...right?
Any suggestions?



