【问题标题】:How to validate for illegal fields in Model Validation如何在模型验证中验证非法字段
【发布时间】:2021-09-27 23:02:28
【问题描述】:

我有一个接受 PersonDto 的 .NET Core 2.2 web-api,它正在使用模型验证进行验证,但它不检查非法字段。它只检查匹配字段是否有效。

我想确保提供的 JSON 仅包含我的 Dto(类)中的字段。

public class PersonDto
  {
    public string firstname { get; set; }
    public string lastname { get; set; }
  }

我的控制器看起来像这样简化:

public async  Task<ActionResult<Person>> Post([FromBody] PersonDto personDto)
{
    // do things
}

我发送的字段不正确(名称在我的 dto 中不存在)并且 ModelState 有效。

{
  "name": "Diego"
}

我希望模型验证会抱怨“名称”字段不存在。

如何检查非法字段?

【问题讨论】:

  • 为什么要检查未知字段,为什么不能忽略它们?
  • 保护调用客户端不出错。
  • 你应该为此使用 ModelState
  • 你建议如何检查非法字段?看到邢的回答了吗?它将非法字段添加到模型状态错误集合中。有没有更好的办法?
  • 正如我之前所说,没有必要保护客户犯错。假设您有一个需要名称和年龄的模型,如果您传递这些值并且高度 ModelState.IsValid 返回 true 并忽略高度。但是,如果您只传递名称和高度 ModelState.IsValid 将返回 false。所以我不明白你为什么要做一个额外的过滤器。您唯一添加的就是额外的同谋并降低性能。只是我的 2 美分。

标签: asp.net-core asp.net-core-webapi


【解决方案1】:

您可以使用ActionFilterReflection 将请求正文内容与模型字段进行比较。如果有意外字段,手动添加模型错误,ModelState.IsValid 为 false。

1.创建一个ActionFilter

public class CompareFieldsActionFilter : ActionFilterAttribute
{

    public override void OnActionExecuting(ActionExecutingContext context)
    { 
        //get all fields name
        var listOfFieldNames = typeof(PersonDto).GetProperties().Select(f => f.Name).ToList();

        var request = context.HttpContext.Request;
        request.Body.Position = 0;

        using (var reader = new StreamReader(request.Body))
        {
            //get request body content
            var bodyString = reader.ReadToEnd();                

            //transfer content to json
            JObject json = JObject.Parse(bodyString);

            //if json contains fields that do not exist in Model, add model error                
            foreach (JProperty property in json.Children())
            {
                if (!listOfFieldNames.Contains(property.Name))
                {
                    context.ModelState.AddModelError("Filed", "Field does not exist");                      
                }
            }
        }
        base.OnActionExecuting(context);
    }
}

2.对你的操作使用过滤器:

[HttpPost]
[CompareFieldsActionFilter]
public async  Task<ActionResult<Person>> Post([FromBody] PersonDto personDto)
{
   if (ModelState.IsValid)
    {
       // do things
    }
  // do things
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    相关资源
    最近更新 更多