开发者

How to modify posted form data within controller action before sending to view?

I want to render the same view after a successful action (rather than use RedirectToAction), but I need to modify the model data that is rendered to that view. The following is a contrived example that demonstrates two methods that that do not work:

    [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 *开发者_StackOverflow/
        product.ProductName = "This has no effect";
        ViewData["ProductName"] = "This has no effect either";

        return View(product);
    }

Does anyone know what the correct method is for accomplishing this?


After researching this further, I have an explanation why the following code has no effect in the Action:

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

My View uses HTML Helpers:

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

HTML Helpers uses the following order precedence when attempting lookup of the key:

  1. ViewData.ModelState dictionary entry
  2. Model property (if a strongly typed view. This property is a shortcut to View.ViewData.Model)
  3. ViewData dictionary entry

For HTTP Post Actions, ModelState is always populated, so modifying the Model (product.ProductName) or ViewData directly (ViewData["ProductName"]) has no effect.

If you do need to modify ModelState directly, the syntax to do so is:

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

Or, to clear the ModelState value:

ModelState.SetModelValue("ProductName", null);

You can create an extension method to simplify the syntax:

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));
    }
}

Then you can simply write:

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

For more details, see Consumption of Data in MVC2 Views.


The values are stored in ModelState.

This should do what you want:

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

I wouldn't suggest doing that though... the correct method would be to follow the PRG (Post/Redirect/Get) pattern.

HTHs,
Charles

EDIT: Updated to reflect the better was of setting the ModelState value as found by @Gary


This will trigger the model to re-evaluate under simple conditions:

ModelState.Clear();
model.Property = "new value";
TryValidateModel(model);


Perform ModelState.Clear() before you change the model.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜