我目前正在构建一个需要支持两个不同版本的表单。每个版本可能使用不同的表单字段子集。我必须这样做才能支持两个不同的客户端,但我不希望两者都有完全不同的控制器操作。
所以,我试图找到一种方法来使用具有验证属性的强类型模型,但其中一些属性是有条件的。
我能想到的一些方法类似于史蒂夫桑德森的partial validation方法。
我将根据表单的哪个版本处于活动状态来清除过滤器OnActionExecuting中的模型错误。
我想到的另一种方法是使用类似
之类的东西将模型分解成碎片class FormModel
{
public Form1 Form1Model {get; set;}
public Form2 FormModel {get; set;}
}
然后找到一些方法来根据版本验证相应的属性。模型上还会有适用于两者的共同属性,这些属性将始终被验证。
有没有人对此有好的建议?
答案 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
}
}