Swashbuckle.AspNetCore 4.0.1
We using route constraint to define some parameters (mainly guid).
This work fine with swagger if parameter defined at method parameter:
[HttpGet("User({id:guid})")]
public async Task<IActionResult> GetUserById(Guid id)
This will produce correct type and format:
"parameters": [
{
"type": "string",
"name": "id",
"in": "path",
"required": true,
"format": "guid"
}
]
But it does not work if method parameter omitted:
[HttpGet("User({id:guid})")]
public async Task<IActionResult> GetUserById()
This will produce type only, but not the format:
"parameters": [
{
"type": "string",
"name": "id",
"in": "path",
"required": true
}
]
Is this by design? How can we workaround this?
PS this is mainly used for custom OData implementation when parameters parsed inside ODataParser
For a moment I have found following workaround:
public class GuidParameterFilter : IParameterFilter
{
/// <inheritdoc />
public void Apply(IParameter parameter, ParameterFilterContext context)
{
if (context.PropertyInfo == null &&
parameter is NonBodyParameter nonBodyParam &&
context.ApiParameterDescription.RouteInfo?.Constraints != null &&
context.ApiParameterDescription.RouteInfo.Constraints.Any(c => c is GuidRouteConstraint))
{
nonBodyParam.Format = "guid";
}
}
}
same here, but for type int.
I also used your workarount until it's fixed in Swagger generation.
I was looking at this issue and came up with something:
//SwaggerGenerator.cs - GenerateParameter(...)
var parameterType = (apiParameter.ModelMetadata != null)
? apiParameter.ModelMetadata.ModelType
: apiParameter.RouteInfo?.Constraints
.Where(x => RouteConstraintMap.ContainsKey(x?.GetType()))
.Select(x => RouteConstraintMap[x.GetType()])
.FirstOrDefault();
var schema = (parameterType != null)
? _schemaGenerator.GenerateSchema(parameterType, schemaRepository)
: new OpenApiSchema { Type = "string" };
(...)
private static readonly Dictionary<Type, Type> RouteConstraintMap = new Dictionary<Type, Type>
{
{ typeof(BoolRouteConstraint), typeof(bool) },
{ typeof(DateTimeRouteConstraint), typeof(DateTime) },
{ typeof(DecimalRouteConstraint), typeof(decimal) },
{ typeof(DoubleRouteConstraint), typeof(double)},
{ typeof(FloatRouteConstraint), typeof(float) },
{ typeof(GuidRouteConstraint), typeof(Guid) },
{ typeof(LongRouteConstraint), typeof(long) }
};
It's seem to do the trick. Now I'm trying to find out how to write a proper test to it. It look like the method CreateActionDescriptor(...) doens麓t generate the constraint parameter. I'll keep looking for the solution but if someone could give me hint it would be nice. Any ideas @domaindrivendev ?
Any update on this? I've got a controller that uses a GUID accountID as part of the route, and it's not in any of the actions directly, but is necessary.
Most helpful comment
For a moment I have found following workaround: