2010-04-21 28 views
13

我想在成功的動作(而不是使用RedirectToAction)之後呈現相同的視圖,但我需要修改呈現給該視圖的模型數據。以下是一個人爲的示例,演示了兩種不起作用的方法:如何在發送查看之前修改控制器操作中的發佈表單數據?

[AcceptVerbs("POST")] 
    public ActionResult EditProduct(int id, [Bind(Include="UnitPrice, ProductName")]Product product) { 
     NORTHWNDEntities entities = new NORTHWNDEntities(); 

     if (ModelState.IsValid) { 
      var dbProduct = entities.ProductSet.First(p => p.ProductID == id); 
      dbProduct.ProductName = product.ProductName; 
      dbProduct.UnitPrice = product.UnitPrice; 
      entities.SaveChanges(); 
     } 

     /* Neither of these work */ 
     product.ProductName = "This has no effect"; 
     ViewData["ProductName"] = "This has no effect either"; 

     return View(product); 
    } 

有沒有人知道正確的方法是用來完成此操作的?

回答

19

進一步研究之後,我爲什麼下面的代碼在操作沒有任何影響的解釋:

product.ProductName = "This has no effect"; 
ViewData["ProductName"] = "This has no effect either"; 

我的視圖使用HTML助手:

<% Html.EditorFor(x => x.ProductName); 

HTML輔助用途當嘗試查找密鑰時,以下順序優先:

  1. ViewData.ModelState字典條目
  2. Model屬性(如果是強類型視圖。此屬性是一個快捷方式View.ViewData.Model)
  3. ViewData字典條目

對於HTTP發佈操作,ModelState中總是被填充,所以修改模型(product.ProductName)或直接的ViewData(計算機[」 ProductName「])不起作用。

如果確實需要直接修改ModelState中,語法這樣做是:

ModelState.SetModelValue("ProductName", new ValueProviderResult("Your new value", "", CultureInfo.InvariantCulture)); 

或者,要清除的ModelState值:

ModelState.SetModelValue("ProductName", null); 

您可以創建一個擴展方法來簡化語法:

public static class ModelStateDictionaryExtensions { 
    public static void SetModelValue(this ModelStateDictionary modelState, string key, object rawValue) { 
     modelState.SetModelValue(key, new ValueProviderResult(rawValue, String.Empty, CultureInfo.InvariantCulture)); 
    } 
} 

然後,你可以簡單地寫:

ModelState.SetModelValue("ProductName", "Your new value"); 

有關更多詳細信息,請參見Consumption of Data in MVC2 Views

+2

謝謝,這非常有用。我使用此功能可以在輸入錯誤的信用卡號碼後重新顯示信用卡號碼。我很驚訝這個任務是如何不平凡/不直觀的。 – smdrager 2011-12-06 21:36:26

+0

謝謝你的回答 – marathonman 2014-10-03 11:22:10

2

這些值存儲在ModelState

這應該做你想要什麼:

ModelState.SetModelValue("ProductName", "The new value"); 

我不會建議這樣做,雖然...正確的方法是按照PRG (Post/Redirect/Get) pattern

HTHS,
查爾斯

編輯:更新,以反映較好的是設置ModelState值由@Gary

發現
+1

謝謝 - 該解決方案確實沒有工作,但我需要指定「product.ProductName」爲重點,而不僅僅是「產品名稱」。 在我真實的情況下(示例代碼是爲了說明),我需要在驗證失敗後清除特定值,所以我不想重定向。驗證成功後,我遵循您推薦的PRG模式。再次感謝。 – gxclarke 2010-04-22 01:16:57

+0

這是否也會清除任何驗證錯誤? – Mac 2010-04-22 02:02:47

-1

執行ModelState.Clear()更改模型前。

... 
ModelState.Clear() 
dbProduct.ProductName = product.ProductName; 
dbProduct.UnitPrice = product.UnitPrice; 
... 
+0

正如其名稱所示,ModelState.Clear()會刪除整個模型狀態,這是不可取的。 – gxclarke 2010-04-22 01:10:10

0

這將觸發模型簡單的條件下重新評估:

ModelState.Clear(); 
model.Property = "new value"; 
TryValidateModel(model); 
相關問題