2013-12-18 20 views
0

這個問題最好用代碼解釋:的ModelState,TempData的,視圖模型的問題 - 新的視圖模型值會自動被覆蓋

public async Task<ActionResult> Index() 
    { 


     if (TempData.ContainsKey("ModelState")) 
     { 
      ModelState.Merge((ModelStateDictionary)TempData["ModelState"]); 


      var viewModelA= new ViewModelA 
      { 
       FirstName = "John" 
      } 
      return View(viewModelA); 
     } 
    } 



    [HttpPost] 
    public async Task<ActionResult> IndexPostActionMethod(ViewModelB model) 
    { 
     if (ModelState.IsValid) 
     { 

      var result = await DoSomeStuff(); 
      if (result.Succeeded) 
      { 
       DoSomeOtherStuff(); 
      } 
      else 
      { 
       AddErrors(result); 
      } 
     } 





     TempData["ModelState"] = ModelState; 
     return RedirectToAction("Index"); 

    } 

這裏的問題是,當我發佈到IndexPostActionMethodDoSomeStuff()回報false出於某種原因,該通過重定向到Index並在重定向期間將ModelState保存在TempData中,然後在重新顯示錶單/頁時,從ModelState(或從何處獲取值的位置)的值被設置爲@Html.TextBoxFor(m => m.FirstName)而不是我在這裏設置的值:var viewModelA = new ViewModelA { FirstName = "John"}。爲什麼我不能重寫該值,它從哪裏得到?這就像框架自動更新viewModelAModelStatDictionary事件中的任何事件,儘管我創建了一個具有新值的新的ViewModelA

回答

0

不要這樣做。您應該處理GET-POST-Redirect循環的方式是:

public async Task<ActionResult> Index() 
{ 

    var model = new ViewModel 
    { 
     FirstName = "John" 
    } 
    return View(model); 
} 

[HttpPost] 
public async Task<ActionResult> Index(ViewModel model) 
{ 
    if (ModelState.IsValid) 
    { 

     var result = await DoSomeStuff(); 
     if (result.Succeeded) 
     { 
      DoSomeOtherStuff(); 
     } 
     else 
     { 
      AddErrors(result); 
     } 
    } 

    return View(model); 
} 

ModelState規則全部。無論您明確傳遞給視圖,如果該值存在於ModelState中,它將優先。使用TempDataModelState傳遞給另一個視圖就是這樣的代碼味道,「嗅覺」甚至沒有真正覆蓋它。

如果您唯一的目標是對GET操作使用一個視圖模型,對POST操作使用另一個不同的視圖模型,那麼您應該真正停下來並嚴肅地問自己爲什麼需要這樣做。在與MVC合作的多年中,我從來沒有這樣做過,從來沒有這樣做過,我無法想象我需要這樣做的場景。

UPDATE

因此,基於您在評論中規定的情況下,我會設計這樣的:

public class IndexViewModel 
{ 
    public SomeTabViewModel SomeTab { get; set; } 
    public AnotherTabViewModel AnotherTab { get; set; } 
    public FooTabViewModle FooTab { get; set; } 
} 

public class SomeTabViewModel 
{ 
    [Required] 
    public string SomeRequiredField { get; set; } 
} 

public class AnotherTabViewModel 
{ 
    [Required] 
    public string AnotherRequiredField { get; set; } 
} 

public class FooTabViewModel 
{ 
    [Required] 
    public string FooRequiredField { get; set; } 
} 

基本上,你打破了個人POST片放入視圖模型這共同構成了一個大視野模型。然後,模型驗證只跟隨容器的實際內部視圖模型實例。因此,例如,如果僅回發到FooTab.FooRequiredField,則僅實例化FooTab。其他兩個視圖模型屬性將保持爲空,並且不會在內部進行驗證(即它們具有必需的字段並不重要)。

+0

構建一個複雜的購物車頁面,單頁面應用類型的應用程序,具有GET操作的大視圖模型和5個用於POST操作的較小視圖模型。哪些POST操作被調用取決於用戶輸入。需要保留路由/ url,並在後續頁面視圖中使用內置驗證狀態,這就是爲什麼我要將ModelState從一個actionmethod傳遞到另一個actionmethod的原因。 – PussInBoots

+0

可能可能會創建一個新問題,但因爲您似乎對這些類型的場景有很多瞭解。如果您的GET操作具有較大的視圖模型,並且您只想將您的值的子集傳遞給與GET操作具有相同名稱的POST操作,並將視圖模型作爲參數傳遞,並且ModelState.IsValid需要評估爲true ;你會怎麼做呢? – PussInBoots

+0

使用標籤jquery插件btw所以一些值將在POST上爲空,因此ModelState.IsValid將評估爲false,這不是我想要的,因爲這些文本框對用戶是隱藏的。 – PussInBoots

相關問題