3

In a WEB API controller, can we have the same method name with different HTTP Verbs?

  [HttpGet]
        public string Test()
        {
            return "Success Get";
        }


  [HttpPost]
        public string Test(int i)
        {
            return "Success Post";
        }

Swagger does not accept this configuration. I get this error when accessing the API methods:

500 : "Message":"An error has occurred.","ExceptionMessage":"Not supported by Swagger 2.0: Multiple operations with path 'api/Common' and method 'POST'. See the config setting - \"ResolveConflictingActions\" for a potential workaround"

Here is my routeconfig:

  config.Routes.MapHttpRoute(
                name: "DefaultApiByName",
                routeTemplate: "api/{controller}/{action}/{name}",
                 defaults: new { id = RouteParameter.Optional }
                );

            config.Routes.MapHttpRoute(
                name: "DefaultApiByAction",
                routeTemplate: "api/{controller}/{action}"
                );

            config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id=RouteParameter.Optional});
1
  • looks like DefaultApiByAction and DefaultApi are the same. try remove one of them. Commented Jan 25, 2016 at 19:13

4 Answers 4

10

The method names themselves don't matter to Swagger, the routes do. Swagger will blow up with that error when it detects potentially ambiguous routes. An ambiguous route being a single route (base uri) that returns more than 1 type of resource. For some crazy reason, Microsoft Web Api allows you to return different resources for the same URI and this is where you get into trouble with people trying to consume your API (and Swagger).

A single URI should represent a single resource.
Correct way:

  1. GET /apples // returns a list of apples
  2. GET /apples?type=red // returns a list of red apples

Incorrect way:

  1. GET /apples/ // Return a list of apples
  2. GET /apples?type=red // returns a dump truck

Microsoft Web Api allows you to handle a single route with multiple methods and because of this you run a very serious risk of accidentally creating an ambiguous route.

Example of code that will break Swagger:

[HttpGet, Route("apples")]
public HttpResponseMessage GetApples()
{
    return _productRepository.Get(id);
}

[HttpGet, Route("apples")]
pblic HttpResponseMessage GetApples([FromUri]string foo)
{
    return new DumpTruck(); // Say WHAAAAAAT?!
}

A lot of Swagger frameworks scan your code at runtime and create a Swagger 2.0 JSON document. The Swagger UI requests that JSON document and builds the UI that you see based on that document.
Now because the Swagger framework is scanning your code to build the JSON, if it sees two methods that represent a single resource that return different types and it breaks. This happens because Swagger does not know how to represent that URI because it is ambiguous.

Here are some things you can do to help solve this problem:

  1. Make sure that you are representing a single route (base URI) with a single resource type.
  2. If you HAVE to represent a single route with different types (typically a bad idea), then you can ignore routes that make the documentation ambiguous by adding the following attribute to the offending method

    [ApiExplorerSettings(IgnoreApi = true)]

This will tell the documentation to ignore this method completely when documenting the API and Swagger will render. Remember that if you are using #2 then Swagger will NOT render this method which can cause problems for people consuming your APIs.

Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for clear explanation. This really helped.
He asked about the different HTTP verbs and you answered about the same verb. IMO different HTTP verb should not create ambiguity.
2

In config file don't break your default route.

config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

And I solve that problem with that way. Just use that lines before your methods start.

[Route("api/Test")]
[Route("api/Test/{id}")]

Comments

1

Comment out the following code:

config.Routes.MapHttpRoute(
         name: "DefaultApi",
         routeTemplate: "api/{controller}/{id}",
         defaults: new { id = RouteParameter.Optional }
    );

And write the following code:

config.Routes.MapHttpRoute("DefaultApiWithAction", "api/{controller}/{action}");

Comments

1

Add seperate route on your conflicting methods. Such as [Route("GetByType")] above of one and [Route("GetById")] on another.

OR, for ASP.NET Core, on startup file for swagger add the below configuration:

 services.AddSwaggerGen(options =>
            {
                options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.