I have a project MyProject.Api with following structure:
Controllers/
- Api/
- UsersController.cs
- HomeController.cs
Startup.cs
where HomeController.cs looks like this:
namespace MyProject.Api.Controllers
{
public class HomeController : Controller
{
private readonly IHostingEnvironment _hostingEnvironment;
public HomeController(IHostingEnvironment hostingEnv) {...}
[HttpGet]
public async Task<IActionResult> Index() {...}
[HttpGet("sitemap.xml")]
public IActionResult SiteMap() {...}
[HttpGet("error")]
public IActionResult Error() {...}
}
}
and UsersController.cs looks like this:
namespace MyProject.Api.Controllers.Api
{
[Route("api/[controller]")]
public class UsersController : Controller
{
private readonly ApiHelper<UsersController> _apiHelper;
private readonly IUserService _userService;
public UsersController(ILogger<UsersController> logger, IUserService userService) {...}
[HttpPost("login")]
public async Task<JsonResult> Login([FromBody] LoginRequest request) {...}
[HttpPost("register")]
public async Task<JsonResult> Register([FromBody] RegisterRequest request) {...}
[HttpGet("renew")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public async Task<JsonResult> Renew() {...}
}
}
and Startup.cs:
namespace MyProjet.Api
{
public class Startup
{
private IConfiguration Configuration { get; }
public Startup(IConfiguration configuration) {...}
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSwaggerGen(c => c.SwaggerDoc("v1", new Info {Title = "Web Api Docs", Version = "v1"}));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseSwagger();
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); });
app.MapWhen(x => !x.Request.Path.Value.StartsWith("/swagger", StringComparison.OrdinalIgnoreCase), builder =>
{
builder.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
"spa-fallback",
new {controller = "Home", action = "Index"});
});
});
}
}
}
when I load /swagger
the UI loads successfully, but with following error:
Fetch error
Internal Server Error /swagger/v1/swagger.json
and with this error on the server side
System.NotSupportedException: Ambiguous HTTP method for action - WebEssentials.AspNetCore.Pwa.PwaController.ServiceWorkerAsync (WebEssentials.AspNetCore.Pwa). Actions require an explicit HttpMethod binding for Swagger 2.0
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreatePathItem(IEnumerable`1 apiDescriptions, ISchemaRegistry schemaRegistry)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwagger(String documentName, String host, String basePath, String[] schemes)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.SpaServices.Webpack.ConditionalProxyMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.SpaServices.Webpack.ConditionalProxyMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
but all methods have unique route, unique name and their HTTP methods are explicitly bound. I've tried adding [Route("")]
to the HomeController.cs, but that did not work either.
What am I doing wrong?
As @devNull said, the mistake is not in my code but in WebEssentials.AspNetCore.Pwa.PwaController.ServiceWorkerAsync
.
UPDATE:
My pull request with fix (Added explicit HttpMethod bindings) was now merged to WebEssentials.AspNetCore.ServiceWorker repository and will hopefully be available in next release on NuGet with version newer than 1.0.59
OLD SOLUTION:
I found the following solution posted here by Gandii.
public class ApiExplorerIgnores : IActionModelConvention
{
public void Apply(ActionModel action)
{
if (action.Controller.ControllerName.Equals("Pwa"))
action.ApiExplorer.IsVisible = false;
}
}
services.AddMvc(c => c.Conventions.Add(new ApiExplorerIgnores()))
This should hide the PwaController from ApiExplorer which is used by Swashbuckle.
Had the same error but without any third party library involved.
Problem in my code was, that there where public
methods in my controller base class being used by the controller but not to be exposed by the controller.
Example:
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class TestController : GenericController<TestClass>
{
public TestController() : base()
{
}
}
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class GenericController<T1>
{
public GenericController()
{
// ...
}
[HttpGet]
public async Task<ActionResult<IEnumerable<T1>>> Get()
{
// ...
}
public void DoStuff()
{
// ...
}
}
Changing the access modifier of DoStuff
to internal
solved the problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With