Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 499
serge_portima Avatar asked Oct 14 '22 22:10

serge_portima


3 Answers

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;
    }
}
like image 183
serge_portima Avatar answered Oct 24 '22 10:10

serge_portima


Try using only [Required] (instead of [property: Required]), for some reason worked for me

like image 36
sagimar Avatar answered Oct 24 '22 11:10

sagimar


For me it started to work by adding the [ApiController] attribute to the controller.

like image 1
Mohsen Avatar answered Oct 24 '22 11:10

Mohsen