我有我的网页上的某些面板被在某些情况下是隐藏的。
比如我可能有一个“账单地址”和“收货地址”和我不想要验证“送货地址”如果“ShippingSameAsBilling”复选框被选中。
我试图使用新DataAnnotations能力 ASP.NET MVC 2(预览1)来实现这一点。
我需要防止“送货地址”的验证时,不显示它,需要找到办法的方式来实现这一目标。 我主要讲的服务器端,通过反对使用jQuery 。
我怎样才能做到这一点? 我有几个观点,与自定义模型约束力,但我目前最好的解决办法如下。 此方法的任何反馈?
http://bradwilson.typepad.com/blog/2009/04/dataannotations-and-aspnet-mvc.html
对于CheckoutModel我使用这种方法(大多数领域隐藏):
[ModelBinder(typeof(CheckoutModelBinder))]
public class CheckoutModel : ShoppingCartModel
{
public Address BillingAddress { get; set; }
public Address ShippingAddress { get; set; }
public bool ShipToBillingAddress { get; set; }
}
public class Address
{
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Required(ErrorMessage = "First name is required")]
public string FirstName { get; set; }
[Required()]
public string LastName { get; set; }
[Required()]
public string Address1 { get; set; }
}
定制模型绑定消除了与“ShippingAddress”开头,如果它发现任何领域的所有的ModelState错误。 然后 'TryUpdateModel()' 将返回true。
public class CheckoutModelBinder : DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
base.OnModelUpdated(controllerContext, bindingContext);
var model = (CheckoutModel)bindingContext.Model;
// if user specified Shipping and Billing are the same then
// remove all ModelState errors for ShippingAddress
if (model.ShipToBillingAddress)
{
var keys = bindingContext.ModelState.Where(x => x.Key.StartsWith("ShippingAddress")).Select(x => x.Key).ToList();
foreach (var key in keys)
{
bindingContext.ModelState.Remove(key);
}
}
}
}
没有更好的办法?
我可以看到你的困境。 我在寻找其他验证解决方案还针对复杂的验证规则可能适用于不止一个属性给定的模型对象,甚至从一个对象图不同的模型对象许多属性(如果你不幸被验证链接对象像这样)。
的的限制IDataErrorInfo
接口是一个模型对象是否满足有效状态时,简单地无属性有错误。 这是说,一个有效的对象是所有它的属性也都是有效的 。 但是,我可以有一个情况,如果物业A,B和C是有效的-那么整个对象是有效的。 但同时 ,如果属性的无效,但B 和 C,那么对象满足有效性。 我根本没有描述与此条件/规则的方式IDataErrorInfo
接口/ DataAnnotations
属性。
所以,我发现这个委托方法 。 现在很多在MVC乐于助人的进步并没有在写这篇文章的时候存在,但核心概念应该可以帮助您。 而不是使用属性来定义对象的确认条件,我们创建一个验证更复杂的要求委托功能,因为他们授权我们可以重新使用它们。 当然这更多的工作,但使用代表的意思是我们应该能够编写一次验证规则的代码和存储在一个地方(也许服务层)的所有验证规则和 (库尔位)甚至使用MVC 2 DefaultModelBinder
到自动调用验证(没有在我们的控制器动作检查堆-像斯科特的博客说,我们可以用做DataAnnotations
。请参阅最后一段的“强类型UI辅助”标题之前)!
我敢肯定,你可以牛肉上面的文章起来一点与匿名委托象建议的方法Func<T>
或Predicate<T>
和编写自定义代码块的验证规则将使交物业条件(例如条件你提到的地方,如果你的ShippingSameAsBilling
属性为true,那么你可以忽略的送货地址等)更多的规则。
DataAnnotations
用于使物体上简单的验证规则真的用很少的代码容易 。 但是,随着您的要求开发,您将需要验证的更复杂的规则。 在MVC2模型绑定新的虚拟方法,应继续提供我们与我们的未来验证的发明融入MVC框架的途径。
确保你不希望验证的字段不发布到行动。 我们只验证实际上发布的字段。
编辑:(由提问者)
这种行为在MVC2 RC2已经改变:
默认确认系统验证整个模型的默认确认系统在ASP.NET MVC 1.0和ASP.NET MVC 2的预览之前RC 2验证只有那些发送到服务器模型属性。 在ASP.NET MVC 2,新的行为是在对模型验证,所有模型的属性进行验证,无论新值是否被张贴。 依赖于ASP.NET MVC 1.0的行为可能需要更改应用程序。 有关此更改的详细信息,请参阅该条目输入验证与模型验证在ASP.NET MVC的Brad Wilson的博客。
对于更复杂的情况下,我搬到从简单的DataAnnotations客场以下内容: 确认与游客和扩展方法 。
如果你想利用你的DataAnnotations,你将取代像下面这样:
public IEnumerable<ErrorInfo> BrokenRules (Payment payment)
{
// snip...
if (string.IsNullOrEmpty (payment.CCName))
{
yield return new ErrorInfo ("CCName", "Credit card name is required");
}
}
用方法来验证通过DataAnnotations通过名称的属性(我没有大气压)。
我创建了一个局部模型绑定,只有验证提交的键。 出于安全的原因(如果我要借此一步远)我想创建一个数据注解的属性是哪些字段允许标记从模型中排除。 然后,OnModelUpdated校验字段属性,以确保没有不想要underposting回事。
public class PartialModelBinder : DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
// default model binding to get errors
base.OnModelUpdated(controllerContext, bindingContext);
// remove errors from filds not posted
// TODO: include request files
var postedKeys = controllerContext.HttpContext.Request.Form.AllKeys;
var unpostedKeysWithErrors = bindingContext.ModelState
.Where(i => !postedKeys.Contains(i.Key))
.Select(i=> i.Key).ToList();
foreach (var key in unpostedKeysWithErrors)
{
bindingContext.ModelState.Remove(key);
}
}
}
这是不相关的DataAnnotations但你看了流利的验证项目? 它可以让你在你的验证细粒度的控制,如果你有对象到对象验证这两个对象的集合对象将让你去。
此外,它似乎一直在心中与MVC建造,但它也有自己的“ 运行 ”,这样就可以在其他.NET应用程序中使用它,以及它是在我的书的另一个奖金。
文章来源: Conditionally validating portions of an ASP.NET MVC Model with DataAnnotations?