简体   繁体   English

ASP.NET 核心 WebAPI FromBody 属性未验证 object 非参考字段

[英]ASP.NET Core WebAPI FromBody attribute is not validating object non-reference fields

I have action Create inside my controller:我在我的 controller 中有操作 Create:

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

It accepts DTO for Post creation (parameter is marked with [FromBody] attribute).它接受 DTO 来创建 Post(参数标有 [FromBody] 属性)。 That DTO has 2 properties: string(reference type) Content property and System.Guid(value type) property:该 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; }
}

The issue is that when i sending valid object everything is work just fine (both Content and BlodId properties are initialized).问题是,当我发送有效的 object 时,一切正常(Content 和 BlodId 属性都已初始化)。 But when i sending empty object it checking only Content property:但是当我发送空的 object 时,它只检查 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"
        ]
    }
}

If i provide value only for Content property it passes validation and BlogId value is "00000000-0000-0000-0000-000000000000" or Guid.Empty.如果我只为 Content 属性提供值,它将通过验证,并且 BlogId 值为“00000000-0000-0000-0000-000000000000”或 Guid.Empty。 The same thing for all non reference types (eg for int value is 0).所有非引用类型都是一样的(例如,int 值为 0)。

Question 1: "Why it behaves like this?"问题 1:“为什么它会这样?” Question 2: "How to make default validation check non-reference types for emptiness?"问题 2:“如何使默认验证检查非引用类型的空虚?”

UPDATE (useful walkaround) :更新(有用的解决方法)

As Octavio Armenta pointed out in the answer : "You will probably have to create a custom attribute that checks the emptiness of a Guid. If you want to use an attribute.".正如Octavio Armenta答案中指出的那样:“您可能必须创建一个自定义属性来检查 Guid 的空性。如果您想使用属性。”。 I did it like this:我是这样做的:

[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
        };
    }
}

Note: The above code snippet uses a switch expression that is only available since C# 8. You can also use a regular switch statement .注意:上面的代码片段使用了一个仅在 C# 8 之后才可用的switch 表达式。您也可以使用常规switch 语句

The default value of a Guid is Guid.Empty , which passes validation of RequiredAttribute . Guid 的默认值为Guid.Empty ,它通过了RequiredAttribute的验证。 You will probably have to create a custom attribute that checks the emptiness of a Guid.您可能必须创建一个自定义属性来检查 Guid 是否为空。 If you want to use an attribute.如果你想使用一个属性。

Properties for value types are initialized with default values for the value type.值类型的属性使用值类型的默认值进行初始化。 If you change not nullable types to nullable (ie Guid to Guid? ), your validation should work as you expect:如果您将不可为空的类型更改为可空的(即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 is validated as you expect because default value for string is null Content已按预期进行验证,因为字符串的默认值为null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM