Как изменить опубликованные данные формы в действии контроллера перед отправкой для просмотра? - PullRequest
17 голосов
/ 22 апреля 2010

Я хочу отобразить то же представление после успешного действия (а не использовать 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);
    }

Кто-нибудь знает, каков правильный метод для этого?

Ответы [ 4 ]

23 голосов
/ 03 мая 2010

После изучения этого вопроса у меня есть объяснение, почему следующий код не действует в действии:

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

My View использует HTML Helpers:

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

Помощники HTML используют следующий порядок очередности при поиске ключа:

  1. Запись словаря ViewData.ModelState
  2. Свойство модели (если строго типизированное представление. Это свойство является ярлыком для View.ViewData.Model)
  3. Запись словаря ViewData

Для действий HTTP Post всегда заполняется 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 голосов
/ 22 апреля 2010

Значения хранятся в ModelState.

Это должно делать то, что вы хотите:

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

Я бы не советовал делать это, хотя ... правильный способ - следовать шаблону PRG (Post / Redirect / Get) .

HTHS,
Charles

РЕДАКТИРОВАТЬ: Обновлено, чтобы отразить, что лучше было установить ModelState значение, найденное @ Gary

0 голосов
/ 10 декабря 2015

Это приведет к повторной оценке модели в простых условиях:

ModelState.Clear();
model.Property = "new value";
TryValidateModel(model);
0 голосов
/ 22 апреля 2010

Выполните ModelState.Clear () перед изменением модели.

...
ModelState.Clear()
dbProduct.ProductName = product.ProductName;
dbProduct.UnitPrice = product.UnitPrice;
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...