Asp.net mvc 如何支持模型属性的条件验证
我目前正在构建一个表单,它需要支持两个不同的版本。每个版本可能使用不同的表单字段子集。我必须这样做以支持两个不同的客户端,但我不希望两个客户端的控制器操作完全不同 因此,我试图想出一种方法,使用具有验证属性的强类型模型,但其中一些属性是有条件的 我能想到的一些方法与steve sanderson的方法类似 在这里,我将根据表单的激活版本清除过滤器中的模型错误 我想到的另一种方法是使用类似于Asp.net mvc 如何支持模型属性的条件验证,asp.net-mvc,controller,models,data-annotations,Asp.net Mvc,Controller,Models,Data Annotations,我目前正在构建一个表单,它需要支持两个不同的版本。每个版本可能使用不同的表单字段子集。我必须这样做以支持两个不同的客户端,但我不希望两个客户端的控制器操作完全不同 因此,我试图想出一种方法,使用具有验证属性的强类型模型,但其中一些属性是有条件的 我能想到的一些方法与steve sanderson的方法类似 在这里,我将根据表单的激活版本清除过滤器中的模型错误 我想到的另一种方法是使用类似于 class FormModel { public Form1 Form1Model {get; set;
class FormModel
{
public Form1 Form1Model {get; set;}
public Form2 FormModel {get; set;}
}
然后找到一些方法,根据版本验证适当的属性。模型上也会有适用于两者的通用属性,这些属性将始终得到验证
有人对此有什么好的建议吗?我在使用ModelBinder删除ModelState中不需要的错误方面取得了相当的成功 下面是一个
地址模型活页夹的示例。在UI中,我有一个针对美国各州的
,但当国家不是“美国”而支持
文本框时,这一点是隐藏的
modelbinder查看国家并删除不需要的值
至于如何使用验证属性,我认为除非你有非常简单的规则,否则你会很快把自己弄得一团糟
提示:您可以拥有任意数量的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
}
}
ModelBinder:
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一开始我不喜欢它,所以我很高兴你已经喜欢了。对于我正在进行的简单任务,工作得相当好