今天在幫同事解問題的時候,碰到一個明明已經回傳一個新的Model 給前端了,但是資料依然是舊的,原來是ModelState影響了結果。
Code 如下:
@model TestProject1.Model.EditModel
@using (Html.BeginForm("Submit", "Default1"))
{
@Html.TextAreaFor(x => x.Column1)
<input type="submit" value="Submit"/>
}
首先View 很簡單,就是一個TextArea 與 一個Submit Button,Form Submit 會跑到後端的Submit Action 上。
public class Default1Controller : Controller
{
public ActionResult Index(EditModel model)
{
return PartialView("Index",model);
}
public ActionResult Submit(EditModel model)
{
model.Column1 = "Submit Change";
return Index(model);
}
}
再來是Controller ,一進來就是到 Index 然後 Return 「Index」這個 Partial。
畫面如下(沒有美工請見諒):
理論上Submit 後 TextArea 的值會被改成「Submit Change」,但是卻沒有,永遠會變成你輸入的值;
ex:
我在畫面上打了「Harry Test」,再按下 Submit ,也確定Model Column1 的值有被改成「Submit Change」,但畫面就是依然顯示「Harry Test」。後來發現是 ModelState 在搞鬼!Model State 會在我們Model Binding 時幫我們紀錄前端傳回來的值,同時會幫我們儲存Model 的驗證狀態,而前端會優先顯示Model State 的值,所以不管你後端在ViewModel 如何更改都是沒有用的,唯一能做的就是Clear ModelState,如下:
public class Default1Controller : Controller
{
public ActionResult Index(EditModel model)
{
return PartialView("Index",model);
}
public ActionResult Submit(EditModel model)
{
model.Column1 = "Submit Change";
ModelState.Clear();
return Index(model);
}
}
加入了「ModelState.Clear()」即可正常顯示。
後記:
後來對這個機制感到十分不解。
理論上除非是Model 驗證不通過的情況下,不然在Model 驗證通過的情形下,只要我們給了新的Model 就應該幫我們清掉ModelState,在Msdn上跟大家討論了一下,結論是:去建議微軟吧!