Kirsten
Kirsten

Reputation: 18160

Multiple HttpPost methods in controller prevents swagger .json generation

I have an Authors controller in a sample C# ASP.NET Core 2.0 Api and I am using Swashbuckle to generate the Swagger .json.

When I include the following two methods in my AuthorsController the .json does not generate

    [HttpPost(Name = "CreateAuthor")]
     public IActionResult CreateAuthor([FromBody] AuthorForCreationDto author)
    {
      return null //for simplicity repeating the problem
    }

and

[HttpPost(Name = "CreateAuthorWithDateOfDeath")]
public IActionResult CreateAuthorWithDateOfDeath(
        [FromBody] AuthorForCreationWithDateOfDeathDto author)
    {
        return null 
    }

Then when I try to access the Swagger UI I get

Failed to load API definition. undefined ./v1/swagger.json

enter image description here

However if I comment out either method the .json will generate.

In Startup ConfigureServices I have

services.AddSwaggerGen(c => {
    c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();

    c.SwaggerDoc("v1", new Info
    {
        Version = "v1",
        Title = "track3 API",
        Description = "ASP.NET Core Web API",
        TermsOfService = "None",
        Contact = new Contact
        {
            Name = "my name",
            Email = "[email protected]"
        }
    });

});

where

public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
        var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
        var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);

        if (isAuthorized && !allowAnonymous)
        {
            if (operation.Parameters == null)
                operation.Parameters = new List<IParameter>();

            operation.Parameters.Add(new NonBodyParameter
            {
                Name = "Authorization",
                In = "header",
                Description = "access token",
                Required = true,
                Type = "string"
            });
        }
    }
}

and in Configure I have

        app.UseSwaggerUI(c =>
        {
            c.RoutePrefix = "api-docs";
            c.SwaggerEndpoint("./v1/swagger.json", "Api v1");
        });

Why would this be?

[Update]

There is a second similar method in the controller. If I comment out the second method and un-comment the first then the .json will generate. Neither method will appear in Swagger

Here is the code for the Dto

public class AuthorForCreationDto
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTimeOffset DateOfBirth { get; set; }
    public string Genre { get; set; }

    public ICollection<BookForCreationDto> Books { get; set; }
    = new List<BookForCreationDto>();
}

public class AuthorForCreationWithDateOfDeathDto
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTimeOffset DateOfBirth { get; set; }
    public DateTimeOffset? DateOfDeath { get; set; }
    public string Genre { get; set; }
}

public class BookForCreationDto : BookForManipulationDto
{
}

public abstract class BookForManipulationDto
{
    [Required(ErrorMessage = "You should fill out a title.")]
    [MaxLength(100, ErrorMessage = "The title shouldn't have more than 100 characters.")]
    public string Title { get; set; }

    [MaxLength(500, ErrorMessage = "The description shouldn't have more than 500 characters.")]
    public virtual string Description { get; set; }
}

Upvotes: 5

Views: 3703

Answers (2)

CindyH
CindyH

Reputation: 3026

Using Mel's answer was helpful but didn't solve everything for me. I have a .NetCore project.

I used the following code and Swagger worked perfectly.

using Microsoft.AspNetCore.Mvc;


[HttpPost]
[Route("MethodTheFirst")]
public IActionResult MethodTheFirst(string name, int id)
{
}



[HttpPost]
[Route("MethodTheSecond")]
public IActionResult MethodTheSecond(string name)
{
}

Upvotes: 3

Mel
Mel

Reputation: 21

See: Swashbuckle fails in asp.net core with NotSupportedException exception

Name your post methods with:

[HttpPost("DistinctName")]
public IActionResult DistinctName()
{

}
[HttpPost("DistinctName2")]
public IActionResult DistinctName2()
{

}

Upvotes: 2

Related Questions