【问题标题】:.NET 5.0 Web API won't work with record featuring required properties.NET 5.0 Web API 不适用于具有所需属性的记录
【发布时间】:2022-05-19 18:46:02
【问题描述】:

我使用 C# 9.0 record 类型作为 .NET 5.0 Web API 项目的绑定模型。某些属性是必需的。

我正在使用record 位置语法,但收到错误。

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

然后将其公开为我的 Index 操作的绑定模型:

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

但是,每当我尝试发出请求时,都会收到以下错误:

记录类型“Service.Models.Mail”具有在属性“内容”上定义的验证元数据,将被忽略。 “内容”是记录主构造函数中的参数,验证元数据必须与构造函数参数相关联。

我尝试删除 Contents 属性上的属性,但它随后对下一个(先前的)属性失败。我尝试使用[param: …] 而不是[property: …],以及混合它们,但不断收到相同类型的错误。

我浏览了网络,并没有发现任何针对 C# 9 记录以不同方式处理注释的建议。我尽了最大努力,但除了将我的记录转换为 POCO 之外,我没有任何想法。

【问题讨论】:

  • 这是一个有趣的错误。我本来希望指定 [param: …] 属性目标来覆盖它。出于好奇,您是否尝试过将这些作为显式属性分配到您的记录中,而不是使用位置构造函数语法作为隐式属性?我不确定它是否会有所作为,但鉴于该错误突出了构造函数的问题,了解它如何影响错误可能很有用。我还假设您在没有任何属性目标的情况下尝试过此操作(即完全删除 property:)?
  • @JeremyCaney 使用用属性装饰的隐式属性对我有用。
  • 嗯!这很好奇。这似乎是如何使用记录处理注释的一个错误,可能是因为构造函数参数兼作属性定义。很高兴听到您解决了问题。
  • @serge_portima 在记录中,默认情况下需要 all 位置属性。它们成为构造函数的一部分,因此 all 都需要有一个值。将Required 放在属性上没有意义,因为一旦设置就无法更改属性的值。如果您希望属性为非空,则必须对 构造函数参数本身 执行验证
  • @PanagiotisKanavos Swashbuckle 没有按要求识别它们,这是我的目标之一。

标签: asp.net-core-webapi asp.net5 c#-9.0 c#-record-type


【解决方案1】:

我放弃了使用 Positional 构造函数,并且使用了详细的完整属性声明,它可以工作。

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】:

我在 ASP.NET Core Razor 页面上发现了类似的东西:

InvalidOperationException:记录类型“WebApplication1.Pages.LoginModelNRTB+InputModel”在属性“PasswordB”上定义了将被忽略的验证元数据。 “PasswordB”是记录主构造函数中的参数,验证元数据必须与构造函数参数相关联。

来自

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

经过一番挖掘,我发现:https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/ModelBinding/Validation/DefaultComplexObjectValidationStrategy.cs

所以也许正如你所做的那样,详细的声明是前进的方向。

Positional record attributes in ASP.NET Core后台

How do I target attributes for a record class?更多背景

【讨论】:

    【解决方案3】:

    在我的情况下,使用FluentValidation 并保留带有完整声明的属性似乎非常有效。我强烈建议尝试这个高度完善的替代验证库,而不是使用非常旧的标准数据注释

        public record LoginViewModel
        {
            public string Mail { get; init; }
            public string Password { get; init; }
            public bool IsPersistent { get; init; }
        }
    
        public class LoginValidator : AbstractValidator<LoginViewModel>
        {
            public LoginValidator()
            {
                RuleFor(l => l.Mail).NotEmpty().EmailAddress();
                RuleFor(l => l.Password).NotEmpty();
            }
        }
    

    【讨论】:

      【解决方案4】:

      尝试仅使用 [Required](而不是 [property:Required]),由于某种原因对我有用

      【讨论】:

      • 这完全是意料之中且不足为奇的,并且与 OP 已发布的最高投票答案一致。问题是如何使用位置语法将属性应用于 just 属性(或者,就此而言,just 方法参数)。 expected 方法是使用[property: Required],但这似乎不起作用。应用[Required] 完全回避了这个要求。
      【解决方案5】:

      对我来说,它通过将[ApiController] 属性添加到控制器开始工作。

      【讨论】:

        猜你喜欢
        • 2016-10-15
        • 2018-10-12
        • 2019-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-08
        • 1970-01-01
        • 2016-06-04
        相关资源
        最近更新 更多