azure-functions-openapi-extension icon indicating copy to clipboard operation
azure-functions-openapi-extension copied to clipboard

Bug: When having 2 classes with the same name (in different namespaces), the Swagger UI do only show one of the classes

Open IcemanCoolFinger opened this issue 3 years ago • 3 comments

When using 2 classes with the same name, but in different namespaces, only one of the classes is defined in the Swagger UI and the json file. In the below sample, the class MessageBody exists in 2 different namespaces, but only one of them is shown in the Swagger UI and the json file.

The problem can be seen here: https://bugsample-backstrom.azurewebsites.net/api/swagger/ui

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Attributes;
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System.Net;
using System.Threading.Tasks;

//First Dto class
namespace FirstSample
{
    public class MessageBody
    {
        public string EmployeeName { get; set; }
    }
    public class EmployeeMessageDto
    {
        public FirstSample.MessageBody MessageContent { get; set; }
    }
}

//Second Dto class
namespace SecondSample
{
    public class MessageBody
    {
        public string CompanyName { get; set; }
    }
    public class CustomerMessageDto
    {
        public SecondSample.MessageBody MessageContent { get; set; }
    }
}

namespace Functions
{
    public static class FunctionA
    {
        [FunctionName("FunctionA")]
        [OpenApiOperation(operationId: "FunctionA", tags: new[] { "name" })]
        [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
        [OpenApiRequestBody("application/json", typeof(FirstSample.EmployeeMessageDto))]
        [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.OK)]
        public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            return new OkObjectResult(string.Empty);
        }
    }

public static class FunctionB
    {
        [FunctionName("FunctionB")]
        [OpenApiOperation(operationId: "FunctionB", tags: new[] { "name" })]
        [OpenApiSecurity("function_key", SecuritySchemeType.ApiKey, Name = "code", In = OpenApiSecurityLocationType.Query)]
        [OpenApiRequestBody("application/json", typeof(SecondSample.CustomerMessageDto))]
        [OpenApiResponseWithoutBody(statusCode: HttpStatusCode.OK)]
        public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            return new OkObjectResult(string.Empty);
        }
    }
}

IcemanCoolFinger avatar Mar 02 '22 12:03 IcemanCoolFinger

I can confirm this as well. My assumption was that it got confused if using the same route, but it seems to be a more general problem. My guess is the openapi code ignores namespaces when generating the swagger.json and gui.

As it stands now, you cannot use the same class name with different namespaces more than once in your api:s. Workaround is to rename all classes and not rely on namespace.

This is with version 1.3.0. Also tried with 1.2.0 and it's the same there.

MartinWickman avatar Mar 31 '22 07:03 MartinWickman

I had a similar issue. Two DTOs and both DTOs (different namespace) have a inner class with the same name. I found a fix where you should configure the SwaggerGen with builder.Services.AddSwaggerGen(options => options.CustomSchemaIds(i => i.FullName)); but this results in an exception in the ui.

Resolver error at components.schemas.....MyEvent.properties.entries.items.$ref Could not resolve reference: Could not resolve pointer: /components/schemas/...MyEvent+InnerEntry does not exist in document.

The problem ist that the FullName string contains a '+' as separator between main class and inner class.

To fix this kine of problem use: builder.Services.AddSwaggerGen(options => { options.CustomSchemaIds(i => i.FullName?.Replace("+", ".")); });

Now the generator and the ui is working with DTOs with inner classes with same names.

mwilde avatar Aug 09 '22 14:08 mwilde

@mwilde from what I can see AddSwaggerGen is not available in the package this issue relates to - Open Api extension for Azure Functions Microsoft.Azure.WebJobs.Extensions.OpenApi. Are you using Swashbuckle instead?

corey-stidston avatar Sep 12 '22 05:09 corey-stidston

any update on this ticket, when we are expecting it to be released.

Thank you

tadlakha9 avatar Jul 24 '23 04:07 tadlakha9

#610 has addressed this issue. The next v2-preview release will contain this fix.

justinyoo avatar Sep 19 '23 11:09 justinyoo

Any timeline when we have the new tag with this fix.

tadlakha9 avatar Sep 28 '23 05:09 tadlakha9