WHowing
WHowing

Reputation: 151

DateOnly type has added DayOfWeek input in swagger

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

Answers (3)

user28573259
user28573259

Reputation: 1

Try upgrading Swashbuckle.AspNetCore version to 7.1.0

enter image description here

Upvotes: 0

Matt Johnson-Pint
Matt Johnson-Pint

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

Jason Pan
Jason Pan

Reputation: 22082

UPDATE

enter image description here

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" });
            }
        }
    }

}

PREVIOUS

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);
}

enter image description here

Upvotes: 0

Related Questions