首页 > 解决方案 > 如何防止模型属性在 AspNet Core 的 mvc 控制器中被验证?

问题描述

我有一个 MVC 控制器操作,它接收带有一些员工列表的复杂类型。在我的自定义模型活页夹中,我将员工分为接受和拒绝并返回 ExcelEmployeeModel

public class ExcelEmployeeModel
{
    [Required] public String Description { get; set; }
    public List<Employee> Accepted { get; set; }
    public List<Employee> RejectedEmployees { get; set; }
}

public class Employee
{
    public Int32 Id { get; set; }
    [Required] public string FirstName { get; set; }
    [Required] public string LastName { get; set; }
}

似乎 AspNetCore 正在为列表中的每个员工调用验证,如果有任何被拒绝的员工,则将 BadRequest 对象发送回客户端。因此,如果有任何被拒绝的员工,则永远不会执行该操作。

如何防止 RejectedEmployees 等属性获得验证?

能够使用自定义属性装饰我的属性会很好,如下所示:

[NoValidation]
public List<Employee> RejectedEmployees {get;set;}

此 ValidationAttribute 是验证员工项目并从那里返回错误请求的原因。

// Conifguration file StartUp.cs
services.AddMvc(options =>
{
    options.Filters.Add(new ValidateModelAttribute());
}

// Custom validation attribute class
public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }
}

这是应该接收数据的操作,但它没有。

[HttpPost]
public async Task<IActionResult> Post([FromBody] ExcelEmployeeModel model)
{
 ... 
}

标签: c#asp.net-core

解决方案


以下可能是我的最终解决方案。

public class NoValidationAttribute : ValidationAttribute
{
    public static void RemoveValidation(ActionExecutingContext context)
    {
        // Get the properties that contain the [NoValidationAttribute]
        var properties = context.ActionArguments.First().Value.GetType()
            .GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(a =>
                a.GetCustomAttributes(true).OfType<NoValidationAttribute>().Any());

        // For each of the properties remove the modelstate errors.
        foreach (var property in properties)
        {
            foreach (var key in context.ModelState.Keys.Where(k =>
                k.StartsWith($"{property.Name}["))) // Item index is part of key [
            {
                context.ModelState.Remove(key);
            }
        }
    }
}

我的 ValidationModelAttribute 现在如下:

public override void OnActionExecuting(ActionExecutingContext context)
{
    NoValidationAttribute.RemoveValidation(context);

    // Finally validation passes for properties using the [NoValidateAttribute]
    if (!context.ModelState.IsValid)
    {
        context.Result = new BadRequestObjectResult(context.ModelState);
    }
}

// Model using the NoValidationAttribute
public class ExcelEmployeeModel
{
    [Required] public String Description { get; set; }
    public List<Employee> Accepted { get; set; }
    [NoValidation]
    public List<Employee> RejectedEmployees { get; set; }
}

推荐阅读