Dai*_*Dai 5 validation asp.net-mvc model-binding asp.net-mvc-2
我有一个像这样的ViewModel类:
class CaseModel {
public Boolean ClientPresent { get; set; }
public ClientModel Client { get; set; }
}
class ClientModel {
[Required]
public String FirstName { get; set; }
[Required]
public String LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
视图页面包含a <input type="checkbox" name="ClientPresent" />和Html.EditorFor( m => m.Client )部分视图.
这个想法是,当用户提供有关案例(业务域对象)的信息时,他们可以选择不通过取消选中ClientPresent框来指定有关客户端(另一个商业对象)的任何信息.
我希望ASP.NET MVC不对子ClientModel对象执行任何验证 - 但是当表单被POST回服务器时会自动填充CaseModel.Client属性,但是因为FirstName并且LastName(不一定)由用户提供它表示它未通过[Required]验证属性,因此ViewData.ModelState.IsValid返回false并且用户获得验证错误消息.
我怎么能得到它所以CaseModel.Client如果CaseModel.ClientPresent是假的话就不会被证实?
请注意,它ClientModel是一个完全独立的ViewModel类,并在应用程序的其他位置使用(例如在ClientController类中,允许用户编辑客户端的各个实例).
我认识到我的问题与绑定无关,而实际上与验证有关:通过保留值,这意味着当用户重新加载页面时将填充相同的表单字段,我只需要丢弃验证消息,因为它们不是适用的。
为此,我意识到我可以执行模型属性验证,但然后使用一些自定义逻辑来删除验证消息。这是与我所做的类似的事情:
public class CaseModel {
public void CleanValidation(ModelStateDictionary dict) {
if( this.ClientPresent ) {
dict.Keys.All( k => if( k.StartsWith("Client") dict[k].Errors.Clear() );
}
}
}
Run Code Online (Sandbox Code Playgroud)
(显然我的实际代码更健壮,但你明白了总体思路)
CleanValidation 方法由控制器的操作方法直接调用:
public void Edit(Int64 id, CaseModel model) {
model.CleanValidation( this.ModelState );
}
Run Code Online (Sandbox Code Playgroud)
我可能可以通过将CleanValidation方法添加到新接口IComplexModel并让新模型绑定器自动调用此方法来整理此问题,以便控制器不需要调用它本身。
我有这个接口,适用于任何需要复杂验证的 ViewModel:
public interface ICustomValidation {
void Validate(ModelStateDictionary dict);
}
Run Code Online (Sandbox Code Playgroud)
在我原来的例子中,CaseModel现在看起来像这样:
public class CaseClientModel : ICustomValidation {
public Boolean ClientIsNew { get; set; } // bound to a radio-button
public ClientModel ExistingClient { get; set; } // a complex viewmodel used by a partial view
public ClientModel NewClient { get; set; } // ditto
public void Validate(ModelStateDictionary dict) {
// RemoveElementsWithPrefix is an extension method that removes all key/value pairs from a dictionary if the key has the specified prefix.
if( this.ClientIsNew ) dict.RemoveElementsWithPrefix("ExistingClient");
else dict.RemoveElementsWithPrefix("NewClient");
}
}
Run Code Online (Sandbox Code Playgroud)
OnActionExecuting验证逻辑在我的公共类中调用BaseController:
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
base.OnActionExecuting(filterContext);
if( filterContext.ActionParameters.ContainsKey("model") ) {
Object model = filterContext.ActionParameters["model"];
ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState; // ViewData.Model always returns null at this point, so do this to get the ModelState.
ICustomValidation modelValidation = model as ICustomValidation;
if( modelValidation != null ) {
modelValidation.Validate( modelState );
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3330 次 |
| 最近记录: |