针对模型对象内部变量的mvc 5自定义验证

时间:2018-09-18 14:58:03

标签: asp.net-mvc-5

我已经在多个地方搜索了这个问题,但无法准确找到我想要的东西。假设我有这个MVC模型结构:

public class Person {
    [Required] 
    public string Name { get; set; }
    public int Age { get; set; }
}

public class Workers {
    [AgeRequired]
    public Person Pilots { get; set; }
    public Person Chefs { get; set; }
}

这是我的cshtml代码:

@Model Workers
<div>
    <label asp-for="Pilots.Name"></label>
    <input asp-for="Pilots.Name"></input>
    <span asp-validation-for="Pilots.Name"></span>
</div>
<div>
    <label asp-for="Pilots.Age"></label>
    <input asp-for="Pilots.Age"></input>
    <span asp-validation-for="Pilots.Age"></span>
</div>
<div>
    <label asp-for="Chefs.Name"></label>
    <input asp-for="Chefs.Name"></input>
    <span asp-validation-for="Chefs.Name"></span>
</div>
<div>
    <label asp-for="Chefs.Age"></label>
    <input asp-for="Chefs.Age"></input>
    <span asp-validation-for="Chefs.Age"></span>
</div>

人员是一个通用模型类,其中包含有关飞行员或厨师的信息。我想要的是我的AgeRequired自定义验证属性,以使仅当提及飞行员而不是厨师时才需要Age。可以吗?

提交表格后,我可以在后端工作,但是我也希望它也可以在前端工作。这是我的属性代码:

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
    public class AgeRequiredAttribute: ValidationAttribute, IClientModelValidator
    {
        public override bool IsValid(object value)
        {
            Workers workers = value as Workers;
            return workers.Age > 0;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ClientModelValidationContext context)
        {
            yield return new ModelClientValidationRule("agerequired", "{0} is a required field.");
        }
    }
}

这是我用于前端验证的javascript代码:

/// <reference path="jquery.validate.js" />  
/// <reference path="jquery.validate.unobtrusive.js" />  
$.validator.addMethod("agerequired",
            function (value, element, parameters) {
                return value > 0;
            });

$.validator.unobtrusive.adapters.add("agerequired", [], function (options) {
    options.rules.agerequired= {};
    options.messages["agerequired"] = options.message;
});

ClientValidationEnabled和UnobstrusiveJavaScriptEnabled都设置为true。

当我在“年龄”字段本身上具有此自定义属性时,它将起作用,但是这对于飞行员和厨师都是必需的。我只希望飞行员需要它。

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

实际上,我能够为感兴趣的人创建作品。

如果将由MVC生成的data-val- [attribute]直接放入输入标签或选择标签中,然后输入要抛出的错误消息,它将进行前端验证,并且仍然进行后端验证,因为MVC会注意到复杂对象中包含信息。这不是理想的,但可能是我将要做的。

例如:

@Model Workers
<div>
    <label asp-for="Pilots.Name"></label>
    <input asp-for="Pilots.Name"></input>
    <span asp-validation-for="Pilots.Name"></span>
</div>
<div>
    <label asp-for="Pilots.Age"></label>
    <input asp-for="Pilots.Age" data-val-agerequired="Age is Required for Pilots."></input>
    <span asp-validation-for="Pilots.Age"></span>
</div>
<div>
    <label asp-for="Chefs.Name"></label>
    <input asp-for="Chefs.Name"></input>
    <span asp-validation-for="Chefs.Name"></span>
</div>
<div>
    <label asp-for="Chefs.Age"></label>
    <input asp-for="Chefs.Age"></input>
    <span asp-validation-for="Chefs.Age"></span>
</div>

会工作。这不是理想的方法,但是它使我们可以将MVC后端验证保留在同一位置。

答案 1 :(得分:0)

另一种选择是在基类中将人的年龄作为可选。

public int? Age { get; set; }

从Person继承厨师和飞行员。在试用版中,将年龄值设为非可选-您可能还希望使用数据注释来确保年龄最小化

public new int Age { get; set; }

该模型现在是“人员”列表。客户端应该能够确定哪个是可选的,哪个不是