Как изменить опубликованные данные формы в действии контроллера перед отправкой на просмотр?
Я хочу сделать один и тот же вид после успешного действия (вместо использования 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);
}
Кто-нибудь знает, какой правильный метод для этого?
Ответы
Ответ 1
После изучения этого, у меня есть объяснение, почему следующий код не действует в Action:
product.ProductName = "This has no effect";
ViewData["ProductName"] = "This has no effect either";
В My View используются HTML-помощники:
<% Html.EditorFor(x => x.ProductName);
HTML-помощники используют следующий порядок приоритета при попытке поиска ключа:
- Запись словаря ViewData.ModelState
- Свойство Model (если строго типизированное представление. Это свойство является ярлыком для View.ViewData.Model)
- Запись словаря ViewDatali >
Для HTTP-сообщений, ModelState всегда заполняется, поэтому изменение модели (product.ProductName) или ViewData напрямую (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");
Подробнее см. Потребление данных в представлениях MVC2.
Ответ 2
Значения хранятся в ModelState
.
Это должно делать то, что вы хотите:
ModelState.SetModelValue("ProductName", "The new value");
Я бы не предложил сделать это, хотя... правильным методом было бы следовать шаблон PRG (Post/Redirect/Get).
HTHS,
Чарльз
EDIT: обновлено, чтобы лучше отразить значение ModelState
, найденное с помощью @Gary
Ответ 3
Это приведет к переоценке модели при простых условиях:
ModelState.Clear();
model.Property = "new value";
TryValidateModel(model);
Ответ 4
Выполните ModelState.Clear() перед изменением модели.
...
ModelState.Clear()
dbProduct.ProductName = product.ProductName;
dbProduct.UnitPrice = product.UnitPrice;
...