2012-10-03 50 views
4

驗證我有我後兩種查看模式控制器,查詢及預約的頁面。任命嵌套在查詢中。用戶可以選擇在不創建約會的情況下向我們提交查詢。MVC如何忽略嵌套視圖模型

我用的是內置的MVC需要在視圖模型屬性的屬性。

我的問題是,當用戶選擇創建一個沒有預約的查詢時,我該如何優雅地忽略嵌套Appointment視圖模型上的驗證器並讓ModelState.IsValid返回true?

if(!viewModel.CreateAppointment) 
      { 
       //ignore the nested view models validation        
      } 

回答

2

那麼,當使用標準數據屬性時,沒有辦法「優雅地」忽略錯誤。

您有幾種選擇,雖然。快速和骯髒(即不好)的方法是清除控制器中ModelState的相關錯誤。

if (some condition) { 
    ModelState["controlName"].Errors.Clear(); 
} 

您也可以編寫自己的使用條件測試的自定義數據屬性。這裏描述的是這樣的:

http://blogs.msdn.com/b/simonince/archive/2011/02/04/conditional-validation-in-asp-net-mvc-3.aspx

第三種辦法是避開屬性和使用驗證框架,如FluentValidation

最後一個選擇是使用JavaScript來確定數據的正確狀態然後修改表單動作url以發佈到不同的Action方法。然後,您可以使用「綁定」屬性修飾操作方法參數以排除您不需要的數據項。但是,我不會推薦這一個,因爲它要求客戶端參與服務器端驗證過程。

1

這是我最終做的。

這讓我能清晰地在嵌套約會視圖模型的所有錯誤。

if (!viewModel.CreateAppointment) 
      { 
       foreach (var modelError in ModelState) 
       { 
        string propertyName = modelError.Key; 

        if (propertyName.Contains("AppointmentsViewModel")) 
        { 
         ModelState[propertyName].Errors.Clear(); 
        } 
       } 
      } 
4

您可以自定義IgnoreModelError屬性如下圖所示,使用2個獨立的按鈕,在視圖中一個只和一個任命查詢。

// C# 
public class IgnoreModelErrorAttribute : ActionFilterAttribute 
{ 
    private string keysString; 

    public IgnoreModelErrorsAttribute(string keys) 
     : base() 
    { 
     this.keysString = keys; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState; 
     string[] keyPatterns = keysString.Split(new char[] { ',' }, 
       StringSplitOptions.RemoveEmptyEntries); 
     for (int i = 0; i < keyPatterns.Length; i++) 
     { 
      string keyPattern = keyPatterns[i] 
       .Trim() 
       .Replace(@".", @"\.") 
       .Replace(@"[", @"\[") 
       .Replace(@"]", @"\]") 
       .Replace(@"\[\]", @"\[[0-9]+\]") 
       .Replace(@"*", @"[A-Za-z0-9]+"); 
      IEnumerable<string> matchingKeys = _ 
       modelState.Keys.Where(x => Regex.IsMatch(x, keyPattern)); 
      foreach (string matchingKey in matchingKeys) 
       modelState[matchingKey].Errors.Clear(); 
     } 
    } 
} 


[HttpPost] 
[IgnoreModelErrors("Enquiry.Appointment")] 
public ActionResult CreateEnquiryOnly(Enquiry enquiry) 
{ 
    // Code for enquiry only. 
} 

[HttpPost] 
public ActionResult CreateAppointment(Enquiry enquiry) 
{ 
    // Code for appointment. 
} 
0

另一種選擇是,而不是內部查詢嵌套預約做一個視圖模型同時包含預約及查詢模型單獨網頁,然後你可以使用綁定屬性與屬性包含或排除選擇性地選擇你想要一個型號綁定或排除,如下所示。

Public Class EnquiryViewModel 
    { 
     public Appointment App {get; set;} 
     public Enquiry Enq {get; set; } 
    } 

    [HttpPost] 
    //Only bind Enquiry model and it's errors. 
    public ActionResult CreateEnquiryOnly([Bind(Include = "Enq")]EnquiryViewModel enquiry) 
    { 
     if(ModelState.IsValid) 
     { 
     // Code for enquiry only. 
     } 
    }