2011-11-29 63 views
8

我有兩個的ViewModels的(簡化的):驗證嵌套的ViewModels

public class ParentViewModel 
{ 
    public ParentViewModel 
    { 
     Content = new ChildViewModel(); 
    } 

    public ChildViewModel Content { get; set, } 
} 

public class ChildViewModel 
{ 
    [Required] 
    public string Name1 { get; set, } 
    [Required] 
    public string Name2 { get; set, } 
} 

而下面的控制器交動作:

[HttpPost] 
public ActionResult Create(ParentViewModel viewModel) 
{ 
    if (ModelState.IsValid) 
    { 
     // process viewModel -> write something into database 
     return RedirectToAction("Index"); 
    } 
    return View(viewModel); 
} 

現在我發送以下形式的值在後請求身體對應於該動作的URL(在Fiddler Request Builder中手動):

  • Content.Name1 = X

    這工作得很好,在Name1財產填充viewModel.ContentName2null因爲Name2需要模型的狀態是無效的。因此,驗證失敗如預期。

  • Xontent.Name1 = X名1 = X或任何這樣,任何被綁定到viewModel

    現在viewModel.Contentnull(因爲我在構造函數實例化的話),但所有物業Name1Name2null。這是預料之中的。我所做的而不是預計模型狀態爲有效,所以它通過驗證(以後導致數據庫異常,因爲有不可空列)。

我該如何改進此代碼,以便驗證也適用於第二種情況?

我做了三個實驗:

  • 我在ParentViewModel構造除去Content實例化,然後Content是在上面的第二個例子null,但驗證仍然通過。

  • 我添加了一個[Required]屬性的Content屬性(但並未刪除Content的實例在ParentViewModel構造函數)。這完全沒有影響,上述兩個測試的描述行爲是相同的。

  • 我添加了一個[Required]屬性的Content財產ParentViewModel構造去掉Content的實例。這看起來像我想要的那樣工作:在第二個測試Contentnull並且由於[Required]屬性驗證失敗。它應該是這樣的:

    public class ParentViewModel 
    { 
        [Required] 
        public ChildViewModel Content { get; set, } 
    } 
    
    public class ChildViewModel 
    { 
        [Required] 
        public string Name1 { get; set, } 
        [Required] 
        public string Name2 { get; set, } 
    } 
    

我現在可以得出結論,在實例中ParentViewModel構造的Content子屬性是問題的根源和模型綁定本身必須實例子屬性(或不,如果請求中沒有匹配的表單字段),以便具有正確工作的服務器端驗證。

我有幾個其他視圖模型構造函數中的子屬性實例,並沒有注意到這個問題,直到現在。所以,這通常是一種不好的做法?還有其他方法可以解決問題嗎?

+0

我目前正在努力與類似的東西。我的情況只有差異,我有一個ChildViewModels的IEnumerable。我已經嘗試了上面的所有三個選項,似乎沒有任何工作適合我。 –

回答

0

第三種解決方案意譯是好的:

public class ParentViewModel 
{ 
    [Required] 
    public ChildViewModel Content { get; set, } 
} 

public class ChildViewModel 
{ 
    [Required] 
    public string Name1 { get; set, } 
    [Required] 
    public string Name2 { get; set, } 
} 

我使用它現在在幾個地方,並沒有發現任何問題。

0

ModelState.IsValid告訴您是否有任何模型錯誤已添加到ModelState中。

默認的模型聯編程序會爲基本類型轉換問題添加一些錯誤,例如傳遞一個非int數的非數字。您可以根據您使用的任何驗證系統更完整地填充ModelState。我建議查看數據註釋來驗證ViewModels,因爲它工作正常。

此語法可能是錯誤的或舊的。 ModelState.AddModelError(「鑰匙」,異常)

What is ModelState.IsValid valid for in ASP.NET MVC in NerdDinner?

+0

我知道這是*技術上*替代方法,但*實際上*它將意味着以下內容:在每個具有嵌套視圖模型的視圖模型的後續操作中,我必須執行如下操作:'if(viewModel.Content.Name1 == null && viewModel.Content.Name2 == null && ...)ModelState.AddModelError(...);'這看起來不太好。對於數據註釋:我不知道哪一個可以幫助我。我已經在使用'[Required]',這就是我的模型中驗證應該考慮的全部內容。還有其他一些註釋「詭計」嗎? – Slauma