5

I have an issue when using a hidden field in an MVC Form Post. When the hidden field is generated via a HTML Helper it won't preserve it's value during the postback. But when using a HTML tag, it works.

Unfortunately this one has taken me a whole day to work out this work around.

Here is what I'm doing... (excuse any spelling, re-typed code for SO):

View Model

public class SomeViewModel
{
    public int MyProperty1 { get; set; }
    public int MyProperty2 { get; set; }
    public int MyProperty3 { get; set; }
}

Post method

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MyActionMethod(SomeViewModel someViewModel, string command)
{
  ...
  ...
  // someViewModel.MyProperty1
  ...
  ...
}

View

@using (Html.BeginForm("MyActionMethod", "SomeController", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()

    @Html.HiddenFor(m => m.MyProperty1)

    <div class="col-md-2">
        <input type="hidden" value=@Model.MyProperty1 name="MyProperty1" />
        <input type="submit" name="command" value="Button1" class="btn btn-primary" />
        <input type="submit" name="command" value="Button2" class="btn btn-success" />
    </div>
    <div class="col-md-1"></div>
    <div class="col-md-1">
        <input type="submit" name="command" value="Button3" class="btn btn-danger" />
    </div>
    <div class="col-md-8"></div>
}

In the above View code, the HTML helper hidden field (@Html.HiddenFor(m => m.MyProperty1)) does NOT work. But the HTML tag hidden field (input type="hidden" value=@Model.MyProperty1 name="MyProperty1") DOES work. I only have one or the other enabled. Both shown here are for display purposes.

I'd prefer to use the HTML Helper syntax, but can live with the HTML tag.

Things to note:

  1. The View is using multiple submit buttons.

  2. The View is using a partial view. Currently no content in the partial view and nothing is being done with it.

I can't see how these would affect the issue. Thought I'd mention it, in case.

Question: Can anyone explain why the HTML Helper isn't working?


***** UPDATE *****

Thanks to Stephen Muecke for pointing out what needed to be included in my question. Moreover an extra thank you for guessing what I was actually doing but I couldn't articulate it.

I'm updating the View Model property in the ActionMethod(), and when the same View is re-rendered, the View Model property doesn't reflect the new value. Rather it is keeping it's initial value, and not preserving the new value.

OpcodePete
  • 887
  • 1
  • 14
  • 28
  • 2
    Of course it works. What make you think it doesn't. Or are you expecting that if your change the property in the POST method and return the view that it will reflect that change? - which it wont because html helpers use `ModelState` values, not model values for binding –  Jun 10 '15 at 13:13
  • 1
    inspect in browser what actual difference you are getiing between two. – Abbas Galiyakotwala Jun 10 '15 at 13:19
  • 1
    What's the difference between your problem and this one? http://stackoverflow.com/questions/20657706/mvc-4-html-hiddenfor-are-not-updating-on-a-postback – Kaizen Programmer Jun 10 '15 at 13:31
  • 1
    Best guess is that you are trying to change the value and return the view despite your question not stating that. [This answer](http://stackoverflow.com/questions/26654862/textboxfor-displaying-initial-value-not-the-value-updated-from-code/26664111#26664111) should help to explain the issue. –  Jun 10 '15 at 13:35
  • @StephenMuecke that's what I was trying to do :) change the property in the action method, and return it to the view with the changed value. – OpcodePete Jun 10 '15 at 13:38
  • @Michael_B Same issue, thanks :) Reading up on this. – OpcodePete Jun 10 '15 at 13:39
  • 1
    Then you should make that clear in the question. Read the link I gave above which explains the behavior. But the correct approach is to follow the PRG pattern. –  Jun 10 '15 at 13:40
  • @StephenMuecke Will read that link. Thanks. Yes I should have put that snippet in my question. Thought I had covered the whole issue, but missed that bit. Sorry. – OpcodePete Jun 10 '15 at 13:43

1 Answers1

8

Although not obvious and I found it difficult to find many articles on this subject to clarify it for me in the past the default behaviour in ASP.NET MVC is the following:

If you are using HTML Helpers and you are rendering the same View in response to a POST it is assumed that you are responding to failed form validation. Therefore the values before being set in the POST will always be rendered back in the view from ModelState.

You have a few options:

  1. ModelState.Clear(); in your post. Not recommended as the framework has not been designed this way.
  2. Use the Post-Redirect-Get pattern and only display validation failure, as the framework was designed (as @StephenMuecke mentions).
  3. If you are not bothered about validation do not use HtmlHelpers
  4. Use Request.Form values instead and remove the SomeViewModel someViewModel parameter. Wouldn't recommend this as you lose all benefits of model binding.
  5. Use ModelState.Remove for the specific field, again not recommended.

The best article I found on this was article from Simon Ince in 2010:

ASP.NET MVC’s Html Helpers Render the Wrong Value!

Another one by Rick Strahl:

ASP.NET MVC Postbacks and HtmlHelper Controls ignoring Model Changes

hutchonoid
  • 32,982
  • 15
  • 99
  • 104
  • I want show value in my hidden field, in HttpPost. Which ***recommended solution*** ? Do not use HtmlHelpers ? Custom Extensions for HtmlHelpers ? – Kiquenet Nov 23 '18 at 05:12
  • Other option: `[System.Web.Mvc.HiddenInput(DisplayValue = false)]` and use ***EditorFor*** ? – Kiquenet Nov 23 '18 at 05:14
  • *Manually generate the hidden field* OR *Write a custom helper which will use the value of your model and not the one that's being POSTed* https://stackoverflow.com/questions/4837744/hiddenfor-not-getting-correct-value-from-view-model?noredirect=1&lq=1 – Kiquenet Nov 23 '18 at 05:21