验证前的ASP.NET Core 2.0 ModelState过滤器?

时间:2018-02-11 15:04:43

标签: asp.net-core-mvc asp.net-core-2.0

我可以在ASP.NET Core 2.0中执行类似的操作吗?

例如,我有这个ViewModel:

public class TodoViewModel
{
    [Required(ErrorMessage = "Required !")] // <--- Required
    public int? Key { get; set; } // Is Nullable

    [Required(ErrorMessage = "Required !")] // <--- Required
    public int? Value { get; set; } Nullable

    [Required(ErrorMessage = "Required !")] // <--- Required
    public byte Type { get; set; }
}

在View for Example中,我有:

@Html.BeginForm(FormMethod.Post)
{ 
    @if (Model.Type == 1)
    {
        @Html.TextBoxFor(x => x.Key)
        @Html.ValidationMessageFor(x => x.Key)
    }

    @if (Model.Type == 2)
    {
        @Html.TextBoxFor(x => x.Value)
        @Html.ValidationMessageFor(x => x.Key)
    }
}

并且在行动中我有这个:

    [HttpPost]
    public IActionResult Todo(TodoViewModel model)
    {
        // My problem
        // if model.type = 1 return ModelState has error validate for Property (Value) is Required
        // and if model.type = 2 return ModelState has error validate for Property (Key) is Required
        if (!ModelState.IsValid) // <-- Here is my problem
            return View(model);
    }

我不想使用@ Html.HiddenFor()

覆盖其他属性的验证

我尝试使用ActionFilterAttribute:

public class TodoActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        TodoViewModel model = (TodoViewModel) context.ActionArguments["model"];

        if (model.Type == 1)
            model.Value = 0;

        if (model.Type == 2)
            model.Key = 0;
    }
}

但不幸的是,Execute for(OnActionExecuting)是在ModelState验证之后。

有没有具体的方法来做到这一点?

我想排除&#34; Key&#34;的ModelState验证属性如果&#34;类型&#34;财产等于1,

并排除ModelState验证&#34;值&#34;属性如果&#34;类型&#34;财产等于2

2 个答案:

答案 0 :(得分:0)

实现IValidatableObject接口。

using System.ComponentModel.DataAnnotations;
public class TodoViewModel : IValidatableObject
{
    public int? Key { get; set; } 

    public int? Value { get; set; } 

    [Required(ErrorMessage = "Required !")] 
    public byte Type { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Type == 1)
        {
            yield return
              new ValidationResult(errorMessage: "Property (Value) is Required",
                                   memberNames: new[] { "Value" });
        }
        if (Type == 2)
        {
            yield return
              new ValidationResult(errorMessage: "Property (Key) is Required",
                                   memberNames: new[] { "Key" });
        }

   }
}

答案 1 :(得分:-1)

这清楚地表明您确实需要两个 ViewModels。要么就是对ViewModel进行粗略验证,要么在业务逻辑中做更详细的验证。

当然,您可以编写自己的验证属性(但不是通过ActionFilterAttribute,而是继承自ValidationAttribute (Custom Validation Attribute)并将其置于视图模型而不是[Required])),这将检查如果需要,但这基本上只是涵盖/隐藏了你有两种不同类型的模型的意图。

验证属性不是为了强制执行业务规则,它们应该是简单的并且在应用业务验证之前验证数据是否在第一眼看上去很好(这可能需要额外的检查,服务或数据库循环 - 跳闸)。

但请记住,如果您使用自定义验证属性,则不会进行任何客户端验证(通过浏览器中的JavaScript)。您还需要实施AttributeAdapterBase<T> RequiredAttribute Example