如何防止在AspNet Core中的mvc控制器中验证模型属性?

时间:2018-05-24 23:21:44

标签: c# asp.net-core

我有一个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正在为列表中的每个员工调用validate,如果有任何被拒绝的员工,则将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)
{
 ... 
}

1 个答案:

答案 0 :(得分:0)

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

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