【问题标题】:How can I support conditional validation of model properties如何支持模型属性的条件验证
【发布时间】:2010-04-05 21:40:19
【问题描述】:

我目前正在构建一个需要支持两个不同版本的表单。每个版本可能使用不同的表单域子集。我必须这样做以支持两个不同的客户端,但我不希望两者都有完全不同的控制器操作。

所以,我试图想出一种方法来使用具有验证属性的强类型模型,但其中一些属性是有条件的。

我能想到的一些方法类似于史蒂夫·桑德森的partial validation 方法。

我会根据哪个版本的表单处于活动状态来清除过滤器 OnActionExecuting 中的模型错误。

我正在考虑的另一种方法是使用类似的方法将模型分解为多个部分

class FormModel
{

public Form1 Form1Model {get; set;}
public Form2 FormModel {get; set;}
}

然后找到一些方法来根据版本验证适当的属性。模型上还有一些共同属性适用于两者,这些属性始终会得到验证。

有人对此有好的建议吗?

【问题讨论】:

    标签: asp.net-mvc controller models data-annotations


    【解决方案1】:

    我在使用 ModelBinders 从 ModelState 中删除我不需要的错误方面取得了相当大的成功。

    这是Address 模型绑定器的示例。在 UI 中,我有一个用于美国各州的 <SELECT>,但是当国家不是“美国”时,它会被隐藏,而是使用 <INPUT ID=StateOrProvince> 文本框。

    modelbinder 查看国家/地区并删除不需要的值。

    就使用验证属性执行此操作而言 - 我认为除非您有非常简单的规则,否则您很快就会陷入混乱。

    提示:您可以拥有任意数量的模型绑定器,以对整个模型的各个部分进行谨慎处理。例如 - 我的模型中有 2 个 Address 对象,它们每个都会自动应用此行为。

    注册:

    ModelBinders.Binders[typeof(UI.Address)] = new AddressModelBinder();
    

    模型绑定器:

    public class AddressModelBinder : DefaultModelBinder
    {
        protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            base.OnModelUpdated(controllerContext, bindingContext);
    
            // get the address to validate
            var address = (Address)bindingContext.Model;
    
            // remove statecd for non-us
            if (address.IsUSA)
            {
                address.StateOrProvince = string.IsNullOrEmpty(address.StateCd) ? null : CountryCache.GetStateName(address.StateCd);
                bindingContext.ModelState.Remove(bindingContext.ModelName + ".StateOrProvince");
            }
            else
            {
                address.StateCd = null;
                bindingContext.ModelState.Remove(bindingContext.ModelName + ".StateCd");
            }
    
    
            // validate US zipcode
            if (address.CountryCode == "US")
            {
                if (new Regex(@"^\d{5}([\-]\d{4})?$", RegexOptions.Compiled).Match(address.ZipOrPostal ?? "").Success == false)
                {
                    bindingContext.ModelState.AddModelError(bindingContext.ModelName + ".ZipOrPostal", "The value " + address.ZipOrPostal + " is not a valid zipcode");
                }
            }
    
            // all other modelbinding attributes such as [Required] will be processed as normal
        }
    }
    

    【讨论】:

    • 我喜欢西蒙这个想法。我会试一试的。
    • @jeff 我一开始不喜欢 - 所以我很高兴你已经喜欢了。对于我要做的简单任务,工作得很好
    猜你喜欢
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    相关资源
    最近更新 更多