ASP.NET Core WebAPI FromBody 属性未验证对象非引用字段

Posted

技术标签:

【中文标题】ASP.NET Core WebAPI FromBody 属性未验证对象非引用字段【英文标题】:ASP.NET Core WebAPI FromBody attribute is not validating object non-reference fields 【发布时间】: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 Armenta 在answer 中指出的那样:“您可能必须创建一个自定义属性来检查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。

【问题讨论】:

【参考方案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

【讨论】:

以上是关于ASP.NET Core WebAPI FromBody 属性未验证对象非引用字段的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 2.2 WebAPI 405 方法不允许

带你做 WebAPI 迁移 ASP.NET Core 2.0

ASP.NET Core WebApi返回结果统一包装实践

ASP.NET Core - 从 WebApi 提供静态内容 [重复]

ASP.Net Core WebApi几种版本控制对比

获取 ASP .Net Core WebAPI 中的所有身份角色