.NET 5.0 Web API won't work with record featuring required properties

妖精的绣舞 提交于 2021-02-10 07:10:57

问题


I'm using a C# 9.0 record type as a binding model for a .NET 5.0 Web API project. Some of the properties are required.

I'm using the record positional syntax, but am receiving errors.

public record Mail(
    System.Guid? Id,
    [property: Required]
    string From,
    [property: Required]
    string[] Tos,
    [property: Required]
    string Subject,
    string[]? Ccs,
    string[]? Bccs,
    [property: Required]
    Content[] Contents,
    Attachment[]? Attachments
);

This is then exposed as the binding model for my Index action:

public async Task<ActionResult> Index(Service.Models.Mail mailRequest)
{
    …
}

Whenever I try to make a request, however, I receive the following error:

Record type 'Service.Models.Mail' has validation metadata defined on property 'Contents' that will be ignored. 'Contents' is a parameter in the record primary constructor and validation metadata must be associated with the constructor parameter.

I tried removing the attribute on the Contents property, but it then fails for the next (prior) property. I tried using [param: …] instead of [property: …], as well as mixing them, but keep getting the same kind of error.

I looked around the web, and haven't found any suggestion of handling annotations differently for C# 9 records. I did my best, but I'm out of ideas—outside of converting my records to POCOs.


回答1:


I gave up using Positional constructor, and with the verbose full declaration of the properties, it works.

public record Mail
{
    public System.Guid? Id { get; init; }

    [Required]
    public string From { get; init; }

    [Required]
    public string[] Tos { get; init; }

    [Required]
    public string Subject { get; init; }

    public string[]? Ccs { get; init; }

    public string[]? Bccs { get; init; }

    [Required]
    public Content[] Contents { get; init; }

    public Attachment[]? Attachments { get; init; }

    public Status? Status { get; init; }

    public Mail(Guid? id, string @from, string[] tos, string subject, string[]? ccs, string[]? bccs, Content[] contents, Attachment[]? attachments, Status status)
    {
        Id = id;
        From = @from;
        Tos = tos;
        Subject = subject;
        Ccs = ccs;
        Bccs = bccs;
        Contents = contents;
        Attachments = attachments;
        Status = status;
    }
}



回答2:


I found something similar on ASP.NET Core Razor pages getting:

InvalidOperationException: Record type 'WebApplication1.Pages.LoginModelNRTB+InputModel' has validation metadata defined on property 'PasswordB' that will be ignored. 'PasswordB' is a parameter in the record primary constructor and validation metadata must be associated with the constructor parameter.

from

Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata.ThrowIfRecordTypeHasValidationOnProperties()

After some digging, I found: https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/ModelBinding/Validation/DefaultComplexObjectValidationStrategy.cs

So maybe as you've done, the verbose declaration is the way forward.

Positional record attributes in ASP.NET Core background

How do I target attributes for a record class? more background



来源:https://stackoverflow.com/questions/65934513/net-5-0-web-api-wont-work-with-record-featuring-required-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!