2014-04-03 74 views
0

我試圖讓我的腦袋爲什麼(數據註釋)驗證錯誤觸發頁面第一次加載之前,任何提交/帖子。但更重要的是如何解決這個問題。MVC綁定觸發驗證錯誤

讀取SO和interwebs,原因似乎是模型綁定在視圖模型屬性具有值之前觸發視圖模型屬性的驗證錯誤。我不確定這是否屬實,實際情況如何,但這聽起來很合理。

而且我讀過兩種解決方法,這聽起來有點哈克:在一個空的觀點 1.使用ModelState.Clear在上inital頁面加載控制器中的操作方法或 2. Initialiase視圖模型屬性模型構造函數。 (尚未確認此技術)

這兩種技術聽起來都像是解決方法。我寧願瞭解正在發生的事情並適當地設計我的代碼。

有沒有人遇到過這個問題?如果是這樣,你在做什麼?

代碼按要求。您可以在下面看到Property1上的Data Annotation驗證,該驗證在初始請求(即首頁加載)時被觸發。

控制器的操作方法(重構爲簡單起見):

public ActionResult Index([Bind(Include = Property1, Property2, Property3, vmclickedSearchButton)] IndexVM vm, string Submit) 
    { 
     bool searchButtonClicked = (Submit == "Search") ? true : false; 
     if (searchButtonClicked) 
     { 
      PopulateUIData(vm); // Fetch data from database and pass them to VM 

      if (ModelState.IsValid) 
      { 
       vm.clickedSearchButton = true; // Used in the vm to avoid logic execution duing initial requests 

       DoWork(vm); 
       } 
      } 

      return View(vm); 
     } 

     // Inital request 
     IndexVM newVM = new IndexVM(); 
     PopulateUIData(newVM); // Fetch data from database and pass to VM 

     return View(newVM); 
    } 

設計注: 理想我想sepate渲染和submiting邏輯到單獨的動作的方法。 也就是說在[HttpGet] Index()操作方法內渲染,並在[HttpPost] Index()操作方法內提交。 但由於我在視圖中使用ForMethod.Get,因爲此方法用於搜索功能,所以我只能使用[HttpGet]索引操作方法。

視圖模型(重構爲簡單起見):

public class IndexVM 
{ 
    // DropDownLists 
    public IEnumerable<SelectListItem> DDLForProperty1 { get; set; } 
    public IEnumerable<SelectListItem> DDLForProperty2 { get; set; } 
    public IEnumerable<SelectListItem> DDLForProperty3 { get; set; } 

    [Required] 
    public int? Property1 { get; set; }  
    public int? Property2 { get; set; } 
    public int? Property3 { get; set; } 
    public bool vmclickedSearchButton { get; set; } 
} 

注: 視圖模型是非常簡單的。它包含下拉列表,DDL的選定屬性以及其中一個屬性的驗證規則。

添加一個構造函數來視圖模型和初始化屬性的解決方法:

public IndexVM() 
{ 
    this.Property1 = 0; 
} 
+0

可以顯示模型和操作方法嗎? – RyanCJI

+0

通過編輯發表:) –

回答

0

的問題是,您要發送一個無效的模型視圖。

  1. Property1在模型中被要求是一個可空int。這並不能解釋驗證執行的原因,但爲什麼模型無效。

  2. 您的操作方法在初始加載期間正在執行驗證。不管http方法(get或post),模型綁定都會執行驗證。

既然你需要Property1int?)到爲空,顧名思義,當它被實例化模型變得無效。有幾種方法來處理這個(不知道這是最合適不過)

  1. 創建在您的控制器HttpGetHttpPost單獨的方法。不要爲HttpGet實現綁定。

  2. 使用默認值(因爲你已經完成)

  3. 修改模型,使Property1不能爲空(即int)。

+0

你100%正確!一旦我修復了模型屬性(即屬性現在不可空,並且還有Requried數據註釋),驗證規則不再在加載時觸發,即與您的選項3一起使用。這看起來比選項更清晰(更簡單) 2。 –