【问题标题】:ASP.NET Core WebAPI FromBody attribute is not validating object non-reference fieldsASP.NET Core WebAPI FromBody 属性未验证对象非引用字段
【发布时间】:2020-11-07 15:39:40
【问题描述】:

我在我的控制器中创建了动作:

[HttpPost]
public async Task<IActionResult> Create([FromBody] PostCreate createDto)
{
    // do something with Create DTO
}

它接受 DTO 来创建 Post(参数标有 [FromBody] 属性)。该 DTO 有 2 个属性:字符串(引用类型)内容属性和 System.Guid(值类型)属性:

public class PostCreate
{
    [Required(ErrorMessage = "content is required")]
    public string Content { get; set; }

    [Required(ErrorMessage = "blog id is required")]
    public Guid BlogId { get; set; }
}

问题是,当我发送有效对象时,一切正常(Content 和 BlodId 属性都已初始化)。但是当我发送空对象时,它只检查 Content 属性:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "|dfcd1687-4a0b9320d8411509.",
    "errors": {
        "Content": [
            "content is required"
        ]
    }
}

如果我只为 Content 属性提供值,它将通过验证,并且 BlogId 值为“00000000-0000-0000-0000-000000000000”或 Guid.Empty。所有非引用类型都是一样的(例如 int 值为 0)。

问题 1:“为什么会这样?” 问题2:“如何使默认验证检查非引用类型为空?”

更新(有用的解决方法)

正如Octavio Armentaanswer 中指出的那样:“您可能必须创建一个自定义属性来检查Guid 的空性。如果您想使用一个属性。”。我是这样做的:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class NotEmptyAttribute : ValidationAttribute
{
    public const string DefaultErrorMessage = "The {0} field must not be empty";

    public NotEmptyAttribute()
        : base(DefaultErrorMessage) { }

    public override bool IsValid(object value)
    {
        if (value == null)
        {
            return true;
        }

        return value switch
        {
            Guid guid => guid != Guid.Empty,
            // other non-reference types checks
            _ => true
        };
    }
}

注意:上面的代码 sn-p 使用了一个 switch expression,这个 switch expression 只在 C# 8 之后才可用。你也可以使用一个普通的 switch statement

【问题讨论】:

    标签: c# rest asp.net-web-api


    【解决方案1】:

    Guid 的默认值为Guid.Empty,它通过了RequiredAttribute 的验证。您可能必须创建一个自定义属性来检查 Guid 是否为空。如果你想使用一个属性。

    【讨论】:

    • 您也可以按照@Eugene 的建议进行操作并更改为可为空的类型。
    • 抱歉耽搁了。由于我的英语知识平庸,我没有立即明白你在说什么。我遇到了一个类似的解决方案并决定更新这个问题,之后我注意到你在谈论这样一个解决方案。谢谢你的回答。
    【解决方案2】:

    值类型的属性使用值类型的默认值进行初始化。如果您将不可为空的类型更改为可空的类型(即 GuidGuid?),您的验证应该按预期工作:

    public class PostCreate
    {
        [Required(ErrorMessage = "content is required")]
        public string Content { get; set; }
    
        [Required(ErrorMessage = "blog id is required")]
        public Guid? BlogId { get; set; }
    }
    

    Content 已按预期进行验证,因为字符串的默认值为 null

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-29
      • 2021-09-05
      • 2019-03-13
      • 2021-04-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多