41

I have integrated swagger in WebApi 2 application. It works fine when application has single controller. When I added second controller in the application. I got following error :

An error has occurred.","ExceptionMessage":"Not supported by Swagger 2.0: Multiple operations with path 'api/Credential' and method 'GET'. See the config setting - \"ResolveConflictingActions\" for a potential workaround","ExceptionType":"System.NotSupportedException","StackTrace":" at Swashbuckle.Swagger.SwaggerGeneratorOptions.DefaultConflictingActionsResolver(IEnumerable1 apiDescriptions)\r\n at Swashbuckle.Swagger.SwaggerGenerator.CreatePathItem(IEnumerable1 apiDescriptions, SchemaRegistry schemaRegistry)\r\n at Swashbuckle.Swagger.SwaggerGenerator.<>c__DisplayClass7.b__4(IGrouping2 group)\r\n at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable1 source, Func2 keySelector, Func2 elementSelector, IEqualityComparer1 comparer)\r\n at Swashbuckle.Swagger.SwaggerGenerator.GetSwagger(String rootUrl, String apiVersion)\r\n at Swashbuckle.Application.SwaggerDocsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpMessageInvoker.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Web.Http.Dispatcher.HttpRoutingDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Net.Http.DelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Web.Http.Cors.CorsMessageHandler.<SendAsync>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.HttpServer.d__0.MoveNext()"} http://localhost:50950/swagger/docs/v1

In the second controller I have added following two methods.

 string Get(string username, string password);

 string Get(string credential);

If I comment one of the method. Then it works fine.

Any Idea how to fix it?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
user2266837
  • 587
  • 2
  • 5
  • 12
  • http://stackoverflow.com/a/42976546/1335146 – Can Ürek Mar 23 '17 at 12:50
  • You may want to [customize Swashbuckle](https://learn.microsoft.com/en-us/azure/app-service-api/app-service-api-dotnet-swashbuckle-customize). It is then up to you to adapt the filter method to achieve what you need. – Eli May 31 '17 at 14:37

9 Answers9

52

In the file AppStart/SwaggerConfig.cs

First one, you must import Linq

using System.Linq;

And add in the same file, this line

c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());

just inside of:

GlobalConfiguration.Configuration 
                .EnableSwagger(c =>
                    { ...

One consideration: In your controllers, you must use the Http methods :

[HttpGet]
[Route("something")]
public List<model> something(){....}

[HttpGet]
[Route("something2")]
public List<model2> something2(){....}

[HttpPost]
[Route("mypost1")]
public List<model> mypost1(){....}

[HttpPost]
[Route("mypost2")]
public List<model2> mypost2(){....}
Benjamin RD
  • 11,516
  • 14
  • 87
  • 157
  • 10
    This works, but it's important to understand why: if there's two matching routes, it'll only document the 1st one. Changing the method route names might be preferred by some. – RandomUs1r Mar 21 '18 at 21:50
  • 5
    There should be a caveat in the answer. I would discourage people from using this method to solve this error. I'd rather prefer changing the route names. – Kishan Vaishnav May 30 '19 at 10:59
  • @KishanVaishnav that comment doen't apport anything good to the question. The question is clear, also the answer is right related with the question. The question doesn't is "is a good way". Please read again the question and try to apport something constructive – Benjamin RD May 30 '19 at 13:51
  • @MrMins My apologies. I don't understand why you have written about changing the SwaggerConfig. Wouldn't changing the route be sufficient? – Kishan Vaishnav May 31 '19 at 03:40
14

You have two options for the above two methods:

  1. Combine two methods into single one with three parameters - each one will be in the query string

  2. Have separate route urls like - api/controller/byusername and api/controller/bycredentials

Bernard Vander Beken
  • 4,848
  • 5
  • 54
  • 76
Silly John
  • 1,584
  • 2
  • 16
  • 34
3

I understand this is an old thread. And im straying away from the OP Issue slightly. However i recently had this issue and spent a long time trying to figure out what was happening (this page is top of google for the issue). and it may help other from going through hours of pain.

my controllers all extended a base controller and i stupidly had a public function instead of a protected function. So swagger was picking up the public function as a duplicate.

Hope this helps others from spending unnecessary time.

echrom
  • 81
  • 6
  • This was it for me. Swagger was throwing `InvalidOperationException: The method 'get' on path '/Blog' is registered multiple times.` I had a base entity with a single `public` method. `GetUserId()`. Changing this method to `protected` solved the issue for me. Due to the error message I was _sure_ it was something to do with my multiple `GET` methods, one of which took in a string `id` parameter, but no - the public method in base class was it. – Dan Cook Apr 07 '21 at 17:27
2

You can change the route on your controller.

The default value is [Route("api/[controller]")]

You can change to [Route("api/[controller]/[action]")]

1

The problem can also occur in a situation where you use attribute routing.

If the attribute route conflicts with a routingtable route you will have the 'multiple operations' error.

Example:

[HttpGet]
[SwaggerOperation("GetByUsername")]
[Route("[path]/User")]
public IHttpActionResult GetUser(string username)
{

}

more info on attribute routing: https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

FrankyHollywood
  • 1,497
  • 19
  • 18
1

An answer I haven't seen: I bungled up usings.

My controller has some MVC items (List items) and thus has a link:

using System.Web.Http;
using System.Web.Mvc;

Because of this, somehow, it got registered twice (I assume). Problem was fixed by using the full qualification for RoutePrefix/Route/HttpGet and others.

namespace MyNameSpace
{
    [System.Web.Http.RoutePrefix("api/Reports")]
    public class ReportsController
    {
        {...constructor...}

        [System.Web.Http.Route("Scans")]
        [System.Web.Http.HttpGet,ResponseType(typeof(List<ReportClass>))]
        public ascyn Task<HttpResponseMessage> GetScans() {...}
WernerCD
  • 2,137
  • 6
  • 31
  • 51
0

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

Abdus Salam Azad
  • 5,087
  • 46
  • 35
0

Sorry, I answered it too late: the solution to the problem is to remove any route versioning attribute on the controller if you have more than one controller; the swagger picks route from the WebApiConfig by default. Note: You do not need to provide the action name or the route. Just make sure that no two actions have the same name nor signature; of course, it can never compile.

KenTechO
  • 1
  • 2
-1

Add route attribute for the method [Route("ApiAnotherFunction")] and [HttpGet].

abatishchev
  • 98,240
  • 88
  • 296
  • 433