I am using NSwag with an ASP.Net Core API and the Swagger UI client is displaying - asp.net-core

I am using NSwag with an ASP.Net Core API, when I execute the web API and navigates to the Swagger UI it displays the following error:
Fetching resource list: undefined. Please wait. It gives an 404 and tells me that Cannot read property 'substring' of undefined, that when I tried to trace the error is pointing to the Swagger client in self.url.substring. Although the json displayed in the swagger.json is totally correct.
This is my Startup.cs class with the Explorer Solution at the right showing my nuget dependencies:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
// Enable the Swagger UI middleware and the Swagger generator
app.UseSwaggerUi(typeof(Startup).GetTypeInfo().Assembly, settings =>
{
settings.SwaggerUiRoute = "/swagger";
settings.PostProcess = document =>
{
document.Info.Version = "v1";
document.Info.Title = "Analisis API";
document.Info.Description = "A simple ASP.NET Core web API";
document.Info.TermsOfService = "None";
document.Info.Contact = new NSwag.SwaggerContact
{
Name = "Example",
Email = "example#gmail.com",
Url = "http://google.es"
};
document.Info.License = new NSwag.SwaggerLicense
{
Name = "Use under LICX",
Url = "https://example.com/license"
};
};
app.UseMvc();
});
}
And this is my controller:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : Controller
{
public IDatosAnalisis datosManager = new DatosAnalisis();
public IResultado resultadoManager = new Resultado();
[HttpGet]
public ActionResult<String> GetDefault()
{
return "Bienvenido a AnalisisApi";
}
[HttpGet("getResultado/{patologiaId}")]
[ProducesResponseType(typeof(ResultadoDTO), 200)]
public ActionResult<ResultadoDTO> GetResultadoByPatologiaId(int patologiaId)
{
ResultadoDTO result = resultadoManager.getResultadoByPatologia(patologiaId);
return result;
}
/// <summary>
/// Receives the analisis data and evaluates them.
/// </summary>
[HttpPost]
public ActionResult<List<ShortResultDTO>> TestValoresAnalisis(DatosSujetoDTO datosSujeto)
{
List<ShortResultDTO> results = datosManager.postDatosAnalisisAndGetPatologias(datosSujeto);
return results;
}
}
Thanks in advance for any help given!

Same problem here, my workaround: using a custom url to visit Swagger
https://localhost:44336/swagger/index.html?url=/swagger/v1/swagger.json

Related

How to return HTTP 404

I am building an asp.net core Web API and I need to be able to hide some of the actions in a controller.
I use the following code to return HTTP 404 (Not Found):
[HttpGet]
public IActionResult Index()
{
if(!_isEnabled)
{
return NotFound();
}
However, in my browser I get this result:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
"title": "Not Found",
"status": 404,
"traceId": "00-502319d62a6027718d2ee2cb3c9f263f-28de7bfdfb48f2d8-00"
}
I need to make the call as if the controller does not exists and the browser shows this:
How can a Controller returns a "real" HTTP 404 experience as if the controller dos not exists at that route?
Update 1
The answers return a JSON data and response code 404.
I am trying to do something different.
I am trying to hide the controller as if it doesn't exist for security reasons. I like the end user browser see above screenshot (Edge in my example)
Update 2
I changed to the following code:
[HttpGet]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status200OK)]
public IActionResult Index()
{
if(!_isEnabled)
{
return StatusCode(StatusCodes.Status404NotFound);
}
and the controller returns the following result:
{"type":"https://tools.ietf.org/html/rfc7231#section-6.5.4","title":"Not Found","status":404,"traceId":"00-3275026575270e11a4b1a5ab0817776a-a4777e626460faeb-00"}
The behavior is strange. Is it a new feature in aspnet code 6 ?
Update 3
Here is my middleware setup in the Program.c. It is plain oob setup:
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddAzureWebAppDiagnostics();
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddApplicationInsightsTelemetry();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
Solution For Update 1:
Middleware could be your savior here thus can be achived what you are trying to implement.
Controller:
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
// return Ok(NotFound());
return StatusCode(StatusCodes.Status404NotFound);
}
Note: You can choose either of the status pattern.
Middleware:
public class CustomResponseMiddleware
{
private readonly RequestDelegate _next;
public CustomResponseMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext)
{
if (httpContext.Response.StatusCode == 404)
{
httpContext.Response.Redirect("/WrongControllerName/WrongAction");
}
await _next(httpContext);
}
}
Note: As you can see, we are checking the controller status code and checking if any 404 decteced. Once the desired status code we will redirect a controller which doesn't exist at all that eventually generate the expected output.
Register Middleware In Program.cs:
app.UseMiddleware<CustomResponseMiddleware>();
Output:

Swagger is not generating api documentation correctly

I have an asp.net core web api project and I am using version 3.1. I installed the swagger package and configured it, everything is normal, but the API of the swagger page is not seen, why is this, this is the configuration information of my reference document.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddControllers();
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "ToDo API",
Description = "A simple example ASP.NET Core Web API",
TermsOfService = new Uri("https://example.com/terms"),
Contact = new OpenApiContact
{
Name = "Shayne Boyer",
Email = string.Empty,
Url = new Uri("https://twitter.com/spboyer"),
},
License = new OpenApiLicense
{
Name = "Use under LICX",
Url = new Uri("https://example.com/license"),
}
});
// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
public void Configure(IApplicationBuilder app)
{
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger(c =>
{
c.SerializeAsV2 = true;
});
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
I reproduced the problem according to your code. I created a Controller myself, but since the routing address was not added, the first time I opened it was like this:
There is only one default route, but in my project I have added a HomeController which also doesn't show up in that API.
public class HomeController : Controller
{
[HttpGet]
public string Index()
{
return "test";
}
}
This is because I did not add the routing address and it did not display.
[Route("api/[controller]")]
public class HomeController : Controller
{
[HttpGet]
[Route("test")]
public string Index()
{
return "test";
}
}
After adding:
I don't know if you are for this reason, if not, can you explain your steps in detail? Or provide an interface where your swagger does not display the API.
Reference documentation:
Get started with Swashbuckle and ASP.NET Core

I cant show the API versions in response header with ApiVersioning .net Core

I follow the instruction REST API versioning with ASP.NET Core to show My API version in the response header.
This is my Configuration code:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddMvc().AddNewtonsoftJson();
services.AddMvc(opt =>
{
services.AddRouting(env => env.LowercaseUrls = true);
services.AddApiVersioning(opt => {
opt.ApiVersionReader = new MediaTypeApiVersionReader();
opt.AssumeDefaultVersionWhenUnspecified = true;
opt.ReportApiVersions = true;
opt.DefaultApiVersion = new ApiVersion(1, 0);
opt.ApiVersionSelector = new CurrentImplementationApiVersionSelector(opt);
});
}
and this is my Controller :
[Route("/")]
[ApiVersion("1.0")]
public class RootController:Controller
{
[HttpGet(Name =nameof(GetRoot))]
public IActionResult GetRoot()
{
var response = new { href = Url.Link(nameof(GetRoot),null) };
return Ok(response);
}
}
when I test my API with postman I got this result :
I don't know why opt.ReportApiVersions = true; doesn't work.
The reason why it behaves this way is to disambiguate an API controller from a UI controller. In ASP.NET Core, there's not really any other built-in way to do so as - a controller is a controller.
There are a few other ways to change this behavior:
Opt out with options.UseApiBehavior = false as the was the case before [ApiController]
Add a custom IApiControllerSpecification that identifies an API controller (there's a built-in implementation that understands [ApiController])
Replace the default IApiControllerFilter service, which is really just an aggregation over all registered IApiControllerSpecification implementations
I hope that helps
I found the solution. I have to add [ApiController] to my Controller:
[Route("/")]
[ApiVersion("1.0")]
[ApiController]
public class RootController:Controller
{
[HttpGet(Name =nameof(GetRoot))]
public IActionResult GetRoot()
{
var response = new { href = Url.Link(nameof(GetRoot),null) };
return Ok(response);
}
}

Unable to create swagger.json file when using aspnet-api-versioning

I have .NET Core 2.2 application. I am trying to set up API with different versions using Microsoft.AspnetCore.Mvc.Versioning nugetpackage. I followed the samples provided in the repository.
I want to use an API version based on the name of the defining controller's namespace.
Project Structure
Controllers
namespace NetCoreApiVersioning.V1.Controllers
{
[ApiController]
[Route("[controller]")]
[Route("v{version:apiVersion}/[controller]")]
public class HelloWorldController : ControllerBase
{
public IActionResult Get()
{
return Ok();
}
}
}
namespace NetCoreApiVersioning.V2.Controllers
{
[ApiController]
[Route("[controller]")]
[Route("v{version:apiVersion}/[controller]")]
public class HelloWorldController : ControllerBase
{
public IActionResult Get()
{
return Ok();
}
}
}
Note the controllers does not have [ApiVersion] attribute becuase i want the versioning to be defined by the namespace
Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddApiVersioning(
options =>
{
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
options.ReportApiVersions = true;
// automatically applies an api version based on the name of the defining controller's namespace
options.Conventions.Add(new VersionByNamespaceConvention());
});
services.AddVersionedApiExplorer(
options =>
{
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "API v1 ", Version = "v1" });
c.SwaggerDoc("v2", new Info { Title = "API v2", Version = "v2" });
});
// commented code below is from
// https://github.com/microsoft/aspnet-api-versioning/tree/master/samples/aspnetcore/SwaggerSample
//services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
//services.AddSwaggerGen(
// options =>
// {
// // add a custom operation filter which sets default values
// //options.OperationFilter<SwaggerDefaultValues>();
// // integrate xml comments
// //options.IncludeXmlComments(XmlCommentsFilePath);
// });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApiVersionDescriptionProvider provider)
{
// remaining configuration omitted for brevity
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
app.UseSwaggerUI(
options =>
{
// build a swagger endpoint for each discovered API version
foreach (var description in provider.ApiVersionDescriptions)
{
options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
}
});
app.UseMvc();
}
}
Issue
It is not able to generate swagger.json file. When i browse url /swaggger i see error undefined /swagger/v1/swagger.json
found..
i am missing [HttpGet] attribute in ActionMethods

Hangfire Dashboard .net core - authentication works locally, not on server

I've implemented authentication for Hangfire Dashboard as recommended (the Dashboard isn't viewable on the server without authentication).
It wasn't working on the server, so I just set Authorize to always be true:
In startup.cs:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//Other stuff here
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new[] { new MyAuthorizationFilter() }
});
}
In my own class:
/// <summary>
/// Used for Hangfire Dashboard only
/// </summary>
public class MyAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
return true;
}
}
However, even this gets a 403 error returned - yet it works fine locally. The previous auth also works fine locally but not on the server.
I've searched Google but can't find anyone having this error - how can I fix it?
Thanks.
for worked like below:
class MyAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
var httpContext = context.GetHttpContext();
// Allow all authenticated users to see the Dashboard (potentially dangerous).
return httpContext.User.Identity.IsAuthenticated;
}
}
And in startup method use as below:
app.UseAuthentication();
app.UseHangfireDashboard(options: new DashboardOptions()
{
Authorization = new IDashboardAuthorizationFilter[]
{
new MyAuthorizationFilter()
}
});
app.UseHangfireServer();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});