admin管理员组

文章数量:1304936

In previous versions of .NET, I'd used Swashbuckle to add OpenAPI support. It had an examples attribute where I could use SwaggerRequestExample or SwaggerResponseExample attributes to map a request parameter or the response type to an instance of a class so that no matter what mime type I had chosen through the swagger UI, the correct serializer would be used to output a sample of a parameter.

How do I do this without Swagger, using the built in OpenAPI functionality?

My attempt at this through limited understanding of how the built-in OpenAPI works didn't work on several fronts. It didn't render the example in the ui, it created an item in the RequestBody example collection for each property in my sample instance, and it would require me to explicitly handle the serialization for each type of serializer I want to support, whereas the old Swashbuckle or Swagger packages would do that for me. Is creating examples for request body or request parameters, where the serialization of the examples can happen implicitly possible?

app.MapPost("/", (
    IDictionary<string, object>  values, IMyService service) =>
{
    var response = service.CreateTask(values);

    return Results.Ok(response);
})
.WithSummary("Create a new record")
.RequireAuthorization("AllowTaskCreate")
.WithOpenApi(op =>
{
    var sample = new
    {
        number = 123,
        value = "sample"
    };

    foreach (var contentType in op.RequestBody?.Content ?? new Dictionary<string, OpenApiMediaType>())
    {
        switch (contentType.Key)
        {
            case "application/json":
                contentType.Value.Example = OpenApiAnyFactory.CreateFromJson(JsonSerializer.Serialize(sample));
                break;

            case "application/xml":
                throw new NotImplementedException();
                break;
        }
    }

    return op;
});

In previous versions of .NET, I'd used Swashbuckle to add OpenAPI support. It had an examples attribute where I could use SwaggerRequestExample or SwaggerResponseExample attributes to map a request parameter or the response type to an instance of a class so that no matter what mime type I had chosen through the swagger UI, the correct serializer would be used to output a sample of a parameter.

How do I do this without Swagger, using the built in OpenAPI functionality?

My attempt at this through limited understanding of how the built-in OpenAPI works didn't work on several fronts. It didn't render the example in the ui, it created an item in the RequestBody example collection for each property in my sample instance, and it would require me to explicitly handle the serialization for each type of serializer I want to support, whereas the old Swashbuckle or Swagger packages would do that for me. Is creating examples for request body or request parameters, where the serialization of the examples can happen implicitly possible?

app.MapPost("/", (
    IDictionary<string, object>  values, IMyService service) =>
{
    var response = service.CreateTask(values);

    return Results.Ok(response);
})
.WithSummary("Create a new record")
.RequireAuthorization("AllowTaskCreate")
.WithOpenApi(op =>
{
    var sample = new
    {
        number = 123,
        value = "sample"
    };

    foreach (var contentType in op.RequestBody?.Content ?? new Dictionary<string, OpenApiMediaType>())
    {
        switch (contentType.Key)
        {
            case "application/json":
                contentType.Value.Example = OpenApiAnyFactory.CreateFromJson(JsonSerializer.Serialize(sample));
                break;

            case "application/xml":
                throw new NotImplementedException();
                break;
        }
    }

    return op;
});
Share Improve this question edited Feb 5 at 2:56 Qiang Fu 8,9791 gold badge6 silver badges16 bronze badges asked Feb 3 at 22:05 JeremyJeremy 46.4k71 gold badges213 silver badges353 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I think you have to handle the serialization for each type of serializer, such as following sample:

    public class ResponseMessage
    {
        public string Message { get; set; }
    }

    public class Person
    {
        public string Name { get; set; }
    }
internal class Program
{
    public static string SerializeToXml<T>(T obj)
    {
        var serializer = new XmlSerializer(typeof(T));
        using var stringWriter = new StringWriter();
        serializer.Serialize(stringWriter, obj);
        return stringWriter.ToString();
    }
...
    private static void Main(string[] args)
    {
        app.MapPost("/example", (Person request) =>
            Results.Ok(new ResponseMessage { Message = $"Hello, {request.Name}!" })
        )
        .WithOpenApi(operation =>
        {
            operation.RequestBody = new OpenApiRequestBody
            {
                Content =
                {
                    ["application/json"] = new OpenApiMediaType
                    {
                        Example = OpenApiAnyFactory.CreateFromJson("""{"name": "John Doe"}""")
                    },
                    ["application/xml"] = new OpenApiMediaType
                    {
                        Example = new OpenApiString(SerializeToXml(new Person { Name = "John Doe" }))
                    }
                }
            };

            operation.Responses["200"] = new OpenApiResponse
            {
                Description = "Success",
                Content =
                {
                    ["application/json"] = new OpenApiMediaType
                    {
                        Example = OpenApiAnyFactory.CreateFromJson("""{"message": "Hello, John Doe!"}""")
                    },
                    ["application/xml"] = new OpenApiMediaType
                    {
                        Example = new OpenApiString(SerializeToXml(new ResponseMessage { Message = "Hello, John Doe!" }))
                    }
                }
            };

            return operation;
        });

本文标签: aspnet coreNET 9 Minimal API OpenAPI parameter examplesStack Overflow