2009-05-07 78 views
5

我有一個問題出現在我嘗試發佈的表單中。在表單未驗證的情況下,我將調用ModelState.AddModelError()的標準路由,然後返回View結果。ASP.Net MVC ModelState/Html.TextBox回發問題

問題是,HTML。*助手應該在呈現時拾取發佈的值,並且我注意到我的文本字段只有在將它們包含在回發操作的參數列表中時纔會這樣做,由於某些表單有太多的字段需要將它們全部列爲參數,因此不需要查看。

我的動作代碼大致是:

Minimum: <%= Html.TextBox("MinVolume", null, new { size = 5 })%> 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(long? id, string name) 
{ 
    var dataDefinition = ... 

    // do some validation stuff 
    if (!ModelState.IsValid) 
    { 
     // manually set checkbox fields via ViewData seeing as this STILL doesn't work in MC 1.0 :P 
     // ... 
     return View(dataDefinition); 
    } 

} 

現在,dataDefinition(這是一個LINQ到SQL實體)具有場MinVolume,在視圖中由這一行處理

然而,當ModelState驗證失敗後呈現視圖時,我們發佈的原始頁面中鍵入的值將不會保留,除非將其作爲參數包含在回發方法中。從字面上看,我可以通過這樣做來「解決問題」:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(long? id, string name, string minVolume) 

由於某些原因,將強制保留字段值。這對我來說似乎很愚蠢,因爲我的表單的方式更多,而且我不應該爲該字段添加參數。

任何想法?

回答

4

會不會是你的代碼:

<%= Html.TextBox("MinVolume", null, new { size = 5 })%> 

..has的null默認值PARAM?也許如果你將null更改爲Model.MinVolume,它會保留價值。像這樣:

<%= Html.TextBox("MinVolume", Model.MinVolume, new { size = 5 })%> 

我不確定您的動作在模型壽命中是否返回值MinVolume。如果是這樣,上述應該工作。否則,您可能需要稍微重構該操作。

+0

不,指定null應該指定現有的模型上下文應該用於查詢值。指定MinVolume是明確的,並會強制使用該值而不是以前提交的值。 – 2009-05-13 08:37:13

+0

不正確。指定MinVolume將查找ViewDataDoctionary,然後查找ModelStateDictionary以查找後續帖子。因此,如果Model.MinVolume說5 becore編輯,然後指定MinVolume將5放入文本框。然後,如果發佈了一個帖子(比如說值3)但是發現無效,那麼TextBox將在第二輪顯示3。你試過了嗎?您通常在「新建」或「創建」視圖上指定空值,以便初始帖子在字段中顯示爲空,隨後的帖子會保留輸入的值。 – 2009-05-13 09:20:28

+0

這正是我每次都這樣做的方式。我從來沒有見過任何你必須指定null的地方。一個鏈接到你看到的地方會很好。 – sirrocco 2009-05-18 16:13:49

3

當您在ModelState中設置錯誤值時,您正在使用什麼鍵?設置TextBox的值參數的代碼如下所示:

downloaded framework code的相關部分。

string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string)); 
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter), isExplicitValue); 

正如您所看到的,如果嘗試值存在,它將使用它 - 但只有當相同的密鑰可用時。

我知道這是有效的,因爲我有一個不帶參數的操作,直接從ValueProvider獲取值,它使用AddModelError指示驗證錯誤。我確信我的文本框中的值被保留。

編輯:爲了保留值,它們需要以某種方式與模型相關聯。一種方法是將它們添加到參數列表中。另一種方法是使用UpdateModel(使用白名單中的參數名稱或沒有白名單)。第三種方法是在@ Jenea的答案中將參數明確地添加到模型中。由於輔助者只從模型狀態中拉出,他們必須在那裏才能保留值。它不查看請求的表單屬性。

+0

那場未通過驗證根本不需要在這個階段。因此,它只是一種「無辜的旁觀者」的形式,並且如果其他領域之一沒有表現出自己的行爲,並因此導致形式再次出現,它將保留其新的價值。 – 2009-05-07 14:57:44

+0

如果我錯誤地假設ModelState應該試圖保留名稱與模型匹配的所有字段,我很想知道所有突然事件。也許它只保留通過參數列表傳入的字段或通過AddModelError引用的字段?如果是這樣的話,看起來有點愚蠢,因爲我當然想要保留表格中的所有內容,而不僅僅是特定的情況。然後再次,MVC仍然沒有妥善保存複選框字段...... – 2009-05-07 15:06:44

0

據我瞭解的解決方案是:

[Transaction] 
[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(int id, FormCollection form) 
{ 
    T itemToUpdate = repository.Get(id); 
    UpdateModel(itemToUpdate, form.ToValueProvider()); 

    if (itemToUpdate.IsValid()) 
    { 
     repository.SaveOrUpdate(itemToUpdate); 
     return Json(ValidationResultToJson(itemToUpdate.ValidationResults())); 
    } 

    repository.DbContext.RollbackTransaction(); 
    return Json(ValidationResultToJson(itemToUpdate.ValidationResults())); 
} 

好運!

6

哦,我剛剛改進了我的應用程序設計。 發生該問題是因爲您有自定義驗證(我也有)。 您必須添加後

ModelState.AddModelError() 

ModelState.SetModelValue("MinVolume", ValueProvider["MinVolume"]); 

鑑於它必須是

Mimum:<%=Html.Textbox("MinVolume")%> 

仍然不知道爲什麼它的工作原理,但它爲我工作。

+0

oooh ...這可能是答案!將在我早上上班時檢查。謝謝。 – 2009-05-14 22:42:48

+2

它可以工作,因爲它將值添加到模型中,幫助者從中提取值。使用UpdateModel也可以,我使用的是爲什麼我的文本框的值被保存。 – tvanfosson 2009-05-15 10:41:14

0

另一種方案是,如果你在查看方式:

<%var minVolume=Request["MinVolume"]??"";%> 
<%=Html.Textbox("MinVolume",minVolume,new {size=5})%> 
0

請參考這篇文章,看看不同的方式來處理回發在ASP.NET MVC

link text

+0

首發的好文章。 – 2009-10-06 21:58:17