我如何支持模型属性的条件验证

时间:2010-04-05 21:40:19

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

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

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

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

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

我想到的另一种方法是使用类似

之类的东西将模型分解成碎片
class FormModel
{

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

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

有没有人对此有好的建议?

1 个答案:

答案 0 :(得分:3)

使用ModelBinder从ModelState中删除我不需要的错误,我取得了一定的成功。

以下是Address模型绑定器的示例。在用户界面中,我有一个<SELECT>美国州,但当国家不是'美国'而支持<INPUT ID=StateOrProvince>文本框时,这是隐藏的。

模型绑定器查看国家/地区并删除不需要的值。

就使用验证属性这样做 - 我认为除非你有非常简单的规则,否则你很快会陷入困境。

提示:您可以根据需要设置尽可能多的模型绑定器,以保留整体模型的各个部分。例如 - 我的模型中有2个Address个对象,它们各自自动应用此行为。

<强>注册

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

<强> ModelBinder的:

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