Swashbuckle.webapi: error opening ui

Created on 9 Dec 2015  路  18Comments  路  Source: domaindrivendev/Swashbuckle.WebApi

Hi, I just added the rc1 version to an aurelia app, configured startup and tried to open the ui and I see this

untitled

I suppose that the error is:
An unhandled exception occurred while processing the request.

NotSupportedException: Unbounded HTTP verbs for path 'api/Attivita/GetLatest/{last}'. Are you missing an HttpMethodAttribute?

but this is the declaration of the action inside the controller

    [Route("[action]/{last:int}")]
    [HttpGet("{last}")]
    public IEnumerable<UltimaAttivitaVm> GetLatest(int last)
    {

am I missing something?

waiting for response

Most helpful comment

Just figured out how to do this... By setting DocInclusionPredicate in my setup I was able to ignore methods that don't have a specified HttpMethod.

The source code that helped me come to this conclusion: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerGen/Generator/SwaggerGenerator.cs#L84

My fix:

services.AddSwaggerGen(c =>
{
    c.DocInclusionPredicate((docName, apiDesc) =>
    {
        if (apiDesc.HttpMethod == null) return false;
        return true;
    });
});

Also important to note that I am using dotnet core sdk: 1.0.0-rc4-004771, swagger aspnetcore v1.

By doing this it also removes the need to set methods to protected assuming those methods don't have httpMethod attributes on them.

All 18 comments

Hi, I had the same issue. In our code this was because we had a RouteAttribute both on the controller class and on each action. The issue was solved by putting the full route on each action and removing the attribute from the class.
The RouteAttribute is now also used to replace the RoutePrefixAttribute from MVC5, but this usage does not seem to be supported by Ahoy right now.

@lucamorelli - what is the exact URI that you want expose the GetLatest action with? The combined use of RouteAttribute and HttpGetAttribute seems a little odd to me. If my understanding of those attributes is correct, they're creating two different paths to the same action.

The former creates the "/GetLatest/{last}" and the latter "{last}". Furthermore, a verb constraint is only applied in the second case meaning that the first can actually be invoked via ANY of the HTTP verbs. So, you're example above actually exposes the following routes to that one action:

GET http:///GetLatest/{last}
POST http:///GetLatest/{last}
PUT http:///GetLatest/{last}
DELETE http:///GetLatest/{last}
GET http:///{last}

If you try any one of these through curl or postman, you'll be able to call the action. I'm not sure if this is the desired result but it's this ambiguity that Swashbuckle/Swagger is complaining about - it requires a single canonical URI template per operation.

Again, I'm not sure what you're intention is but if you just want to expose a GET to "GetLatest/{last}", then you could simply do the following:

[HttpGet("[action]/{last}")]
public IEnumerable<UltimaAttivitaVm> GetLatest(int last)
{
    ...
}

I had the same issue but in my case it was because I accidentally had two HttpGet attributes on the same controller action

I am having the same issue. Remove route attribute from controller solve the problem. but test project seems to have Route Attribute on the controller.

I'm still not convinced this is a Swashbuckle issue. Will close for now but feel free to re-open if you have an argument to the contrary

Came across this thread today while googling the same issue. I think if anything the error message isn't specific enough. I realized that my issue was I had public methods in my controller that had no verb assigned... This happened as a result of my code pattern where all of my controllers inherit from a custom, intermediate base controller with some helper functions attached. I resolved the issue by making all of those methods protected instead of public.

Edit: I think the public/protected nature of non-web methods only becomes an issue where your route is defined on the controller as opposed to each method. If you put the route on the controller, all public methods are assumed by Swashbuckle to require being bound to a verb.

So I had the same problem today and the resolution was simple... I had the following two GET attributes on the Controller Action:

[HttpGet]
[HttpGet("id/{id?}")]

While the first one is understandable to WebApi. It is not understandable to Swagger for some reason. I fixed the issue after changing it to this:

[HttpGet("")]
[HttpGet("id/{id?}")]

Hope this helps someone.

I had the same problem , and one of my Method in the controller did not had any Http Attributes in it.

Be sure to check the controller and base class for any public methods.

I had a public method in my base class that I had to change to protected.

If using DI on the controller constructor (e.g. .net core + DBContext) - will still have an issue - constructor doesn't have an HTTP Attribute. Anyone else try this or notice this, and have a workaround?

I have not had an issue with DI and I'm using .Net Core.

Is it possible to have the controller-level route and tell swagger to simply ignore any methods that don't have the HTTP attribute?

Just figured out how to do this... By setting DocInclusionPredicate in my setup I was able to ignore methods that don't have a specified HttpMethod.

The source code that helped me come to this conclusion: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerGen/Generator/SwaggerGenerator.cs#L84

My fix:

services.AddSwaggerGen(c =>
{
    c.DocInclusionPredicate((docName, apiDesc) =>
    {
        if (apiDesc.HttpMethod == null) return false;
        return true;
    });
});

Also important to note that I am using dotnet core sdk: 1.0.0-rc4-004771, swagger aspnetcore v1.

By doing this it also removes the need to set methods to protected assuming those methods don't have httpMethod attributes on them.

@bsell93 Did you do that because you had some public methods in your controllers?

@aaronralls yeah.. Basically. I was inheriting from a BaseController that had public methods.

@bsell93 Do you control that base class? If so those should probably be Protected vs. Public.

@aaronralls I do. That would make sense except then I wasn't able to properly test my base class.

@bsell93 's solution to add DocInclusionPredicate worked for me. Thank you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Misiu picture Misiu  路  3Comments

qwertykeith picture qwertykeith  路  5Comments

raaga123 picture raaga123  路  4Comments

thj-dk picture thj-dk  路  5Comments

nf17 picture nf17  路  4Comments