Open andreasuvoss opened 1 year ago
I think I'm running in to a similar issue. I'm trying to set a boolean
parameter to show as NOT required in Swagger UI. It seems the model property attributes dont flow up
I have the following:
app.MapGet("/", ([AsParameters] GetRequestModel request) => "Hello World!");
public class GetRequestModel
{
[FromQuery(Name = "unassigned_only")]
[JsonPropertyName("unassigned_only")]
[SwaggerParameter(Description = "Property description", Required = false)]
[DefaultValue(false)]
public bool UnassignedOnly { get; set; }
}
The DefaultValue
is displayed on Swagger UI fine, but the SwaggerParameter
seems to have no effect. The Description
isnt displayed on the Swagger UI and the parameter also still shows as "Required". I also tried using SwaggerSchema
attribute, but same result.
I think I'm running in to a similar issue. I'm trying to set a
boolean
parameter to show as NOT required in Swagger UI. It seems the model property attributes dont flow upI have the following:
app.MapGet("/", ([AsParameters] GetRequestModel request) => "Hello World!"); public class GetRequestModel { [FromQuery(Name = "unassigned_only")] [JsonPropertyName("unassigned_only")] [SwaggerParameter(Description = "Property description", Required = false)] [DefaultValue(false)] public bool UnassignedOnly { get; set; } }
The
DefaultValue
is displayed on Swagger UI fine, but theSwaggerParameter
seems to have no effect. TheDescription
isnt displayed on the Swagger UI and the parameter also still shows as "Required". I also tried usingSwaggerSchema
attribute, but same result.
Try change type bool
to bool?
, then enable nullable reference type for project and Swashbuckle.AspNetCore
@codelovercc Thanks for the reply.
While changing it the bool?
does work, its not really desired since I don't want to handle nullable value on the API side. I simply want to display it as optional on the Swagger UI and default to false.
@mr-davidc Welcome, I'm happy to help.
In my case, with project nullable enabled <Nullable>enable</Nullable>
, and
services.AddSwaggerGen(options =>
{
options.SupportNonNullableReferenceTypes();
});
public class MyDto
{
public bool Encrypted {get;set;}
}
MyDto.Encrypted
will be optional on the Swagger UI.
Hi again @codelovercc,
I tried those options you mentioned above, but still my bool
properties come through to Swagger UI as required. I really think the [AsParameters]
is having an impact here.
I also still have an issue where the endpoint Summary doesn't come through to Swagger UI either, UNLESS I set .WithOpenApi()
but then I lose all of my SwaggerParameter
descriptions...
public static RouteGroupBuilder GetItemsRoute(this RouteGroupBuilder routeGroupBuilder)
{
routeGroupBuilder
.MapGet("/", GetItems)
.WithSummary("Retrieve a list of items") <------- This doesnt display on Swagger UI
.ProducesProblem(StatusCodes.Status400BadRequest)
.ProducesProblem(StatusCodes.Status500InternalServerError);
return routeGroupBuilder;
}
Any other things I can try to fix either of these issues?
I have the same problem. Using the data annotation [AsParameters]
to bind to an object. The data annotations seem to work like [DefaultValue()]
, but the summary for any property in the object with AsParameters attribute is not shown in SwaggerUI.
Hi! I want to share my experience as well. I'm also using the data annotation [AsParameters] to bind to an object. The SwaggerParameter
seems to have no effect in the Swagger UI.
record Fruit(string Name, int Stock);
record struct CreateFruitModel
([FromServices] LinkGenerator Links,
[FromRoute]
[SwaggerParameter(Description = "The id of the fruit that will be created", Required = true)] string Id,
[FromBody] Fruit Fruit);
app.MapPost("/fruit/{id}", handler.CreateFruit)
.WithName("CreateFruit");
internal class FruitHandler
{
private readonly ConcurrentDictionary<string, Fruit> _fruit;
public FruitHandler(ConcurrentDictionary<string, Fruit> fruit)
{
_fruit = fruit;
}
/// <summary>
/// Creates a fruit with the given ID, or returns 400 if a fruit with the given ID exists
/// </summary>
/// <param name="model">A model for the parameters we need to create a fruit</param>
/// <response code="201">The fruit was created successfully</response>
/// <response code="400">A fruit with the given ID already exists in the dict</response>
///
[ProducesResponseType(typeof(Fruit), 201)]
[ProducesResponseType(typeof(HttpValidationProblemDetails), 400, "application/problem+json")]
[Tags("fruit")]
public IResult CreateFruit([AsParameters] CreateFruitModel model)
=> _fruit.TryAdd(model.Id, model.Fruit)
? TypedResults.Created(
model.Links.GetPathByName("GetFruitById", new { model.Id })
?? "N/A",
model.Fruit)
: Results.ValidationProblem(new Dictionary<string, string[]>
{
{ "id", new[] { "A fruit with this id already exists" } }
});
}
This is the only thing that I have found to work:
var _fruit = new ConcurrentDictionary<string, Fruit>();
var handler = new FruitHandler(_fruit);
app.MapPost("/fruit/{id}", handler.CreateFruit)
.WithName("CreateFruit")
.WithOpenApi(o =>
{
o.Parameters[0].Description = "The id of the fruit that will be created";
return o;
});
It's not really clear for me which parameters we access with o.Parameters. Here it seems that the collection contains only one parameter: the route id parameter.
Seems like this feature is still missing, anyone know?
This issue is stale because it has been open for 60 days with no activity. It will be automatically closed in 14 days if no further updates are made.
Hi @andreasuvoss, can you test if this is solved with the addition of #2943. You can download the latest bits using myGet. I think that the PR has just done it
@kaloyantihomirov Reviewing this item a bit further I think that you did not use the EnableAnnotations extension method that comes from the nuget package Swashbuckle.AspNetCore.Annotations. Unfortunuately if you apply it, it throws an error that is only present for this specific scenario. I have got it and soon I will write a PR for this matter
@kaloyantihomirov can you test using myGet?, my changes are already merged
Hi @andreasuvoss, can you test if this is solved with the addition of #2943. You can download the latest bits using myGet. I think that the PR has just done it
I’m not at my computer at the moment, I will try to test this sometime next week, maybe already tomorrow.
Hi @andreasuvoss, reviewing the issues with MinimalApi, the issue is that if you use AsParameters the ContainerType is not present over the Parameters of the endpoint(The AsParametersArgument class is missing). I think that we cannot do anything (Let me review it later), apart from recommending you to use the SwaggerParameter attribute
Hi @martincostello, I wasn't able to get the XML parameters to work when they are members of a AsParameters request. It's a limitation on the OpenApi provider that Swashbuckle uses under the hood. Should we create an issue in their GitHub repo or as it's supported with the Attributes, it's at least covered
Sure, that sounds sensible.
It will be supported in dotnet10. dotnet/aspnetcore#56764
Swashbuckle.AspNetCore: 6.5.0 .NET 7
I am not sure if this is a bug or a feature request.
When defining APIs using the minimal API approach, the summaries from models are not lifted from the XML documentation and put into the resulting
swagger.json
like I would expect. Before migrating to minimal API we used controllers, and the[FromQuery]
annotation in a similar way. This gave the expected result. However[FromQuery]
is not supported when using minimal API, instead the[AsParameters]
annotation was added in .NET 7 .The summaries are present in the XML file generated when building the project, but not in the
swagger.json
file.I have created a minimal example showing that the summaries are not present (in both
swagger.json
or SwaggerUI) when using the[AsParameter]
annotation, but they are included in the schema on the post request using the[FromBody]
annotation.I have a very ugly workaround using the
WithOpenApi
extension method from the NuGet packageMicrosoft.AspNetCore.OpenApi
to add descriptions to the individual indices of each parameter by modifying the mapping from my minimal example like so:Minimal example:
Project file:
Program.cs: