Reputation: 151
I need some help understanding why swagger is showing an extra field as part of the input to a POST method using ASP.NET Core.
I have a constructor endpoint like this:
public async Task<IActionResult> AddHours([FromBody] List<HoursForDay> hoursList)
The HoursForDay record looks like this:
public readonly record struct HoursForDay(DateOnly Date, int Hours);
The .NET Core DateOnly struct has 2 ctors that looks like this (https://learn.microsoft.com/en-us/dotnet/api/system.dateonly?view=net-6.0):
DateOnly(Int32, Int32, Int32)
DateOnly(Int32, Int32, Int32, Calendar)
But my swagger page shows this input schema:
[
{
"date": {
"year": 0,
"month": 0,
"day": 0,
"dayOfWeek": "Sunday"
},
"hours": 0
}
]
Can someone help me understand why the "dayOfWeek" attribute is being shown as part of the input?
And how to get rid of it? I'm aware of the option to create a custom type that has just year, month, day attributes, I'm looking for other options.
Upvotes: 1
Views: 900
Reputation: 241808
I believe this is actually a bug, as Swagger should (by now) be handling DateOnly
types correctly. Your generated schema should show an actual date type as a string in yyyy-mm-dd
format, not a custom type with separate properties. I'm not sure what version of .NET you're running, but I was able to reproduce it with 8.0.2 (SDK 8.0.201). I've reported the bug here.
You can workaround by manually mapping DateOnly
in your configuration:
builder.Services.AddSwaggerGen(options => {
options.MapType<DateOnly>(() => new OpenApiSchema {
Type = "string",
Format = "date" });
});
Upvotes: 1
Reputation: 22082
builder.Services.AddSwaggerGen(c =>
{
c.SchemaFilter<DateOnlySchemaFilter>();
});
HoursForDay.cs
namespace WebApplication1
{
public readonly record struct HoursForDay(DateOnly Date, int Hours);
}
DateOnlySchemaFilter.CS
namespace WebApplication1
{
public class DateOnlySchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type == typeof(DateOnly))
{
schema.Properties.Clear();
schema.Properties.Add("year", new OpenApiSchema() { Type = "integer" });
schema.Properties.Add("month", new OpenApiSchema() { Type = "integer" });
schema.Properties.Add("day", new OpenApiSchema() { Type = "integer" });
}
}
}
}
Reason
Swagger uses reflection to inspect .NET types and generate schemas based on the properties it finds. DateOnly has DayOfWeek in its properties, so DayOfWeek comes in.
You should use [JsonIgnore]
attributes to avoid it.
Test Code and Result
public readonly record struct HoursForDay
{
[JsonIgnore]
public DateOnly Date { get; init; }
public int Hours { get; init; }
public HoursForDay(DateOnly date, int hours) => (Date, Hours) = (date, hours);
}
Upvotes: 0