Html.HiddenFor outputs blank value first time and correct value if repeated

731 Views Asked by At

I'm using MVC 2. When I do this:

      <%: Html.HiddenFor(model => model.SourceType) %>

I get this in the view:

      <input id="SourceType" type="hidden" value="" name="SourceType">

I confirmed that the model has the correct value before returning the view in the controller. The value is correctly set to 11.

I started trying different things to see if I could get any different result and found that if I repeat the textbox like this:

      <%: Html.HiddenFor(model => model.SourceType) %>
      <%: Html.HiddenFor(model => model.SourceType) %>

Results in this:

      <input id="SourceType" type="hidden" value="" name="SourceType">
      <input id="SourceType" type="hidden" value="11" name="SourceType">

Can anyone think of a reason why the view is rendering the first textbox with a blank value while the second contains the correct value?

EDIT: I thought this might be caused by javascript so I removed all scripts from the page, but the value is still blank the first time and correct when repeated.

EDIT: Based on jle's link I tried this:

      <input type="hidden" value="<%= Html.AttributeEncode(Model.SourceType) %>" id="SourceType" name="SourceType" />
      <input id="SourceType" type="hidden" value="11" name="SourceType">
      <input id="SourceType" type="hidden" value="11" name="SourceType">

And got this:

      <input id="SourceType" type="hidden" name="SourceType" value="">
      <input id="SourceType" type="hidden" value="11" name="SourceType">
      <input id="SourceType" type="hidden" value="11" name="SourceType">

Also, based on the link I tried this in the controller just before returning the view:

      ModelState.Clear();

Result is still the same. The first value to be rendered is blank.

EDIT: Here is the controller code:

      Source source = SourceService.NewSource();
      return View("Source", Mapper.Map(source, new SourceViewModel()));

EDIT: Problem seems isolated to the use of HiddenFor helper.

I did this:

      <%: Model.SourceType %>
      <%: Html.HiddenFor(model => model.SourceType) %>
      <%: Html.HiddenFor(model => model.SourceType) %>

And got this:

      11
      <input id="SourceType" type="hidden" value="" name="SourceType">
      <input id="SourceType" type="hidden" value="11" name="SourceType">

EDIT: Following jle's input I tried this but still no luck:

      <input id="SourceType" type="hidden" value="<%: Model.SourceType %>" name="SourceType">
      <%: Html.HiddenFor(model => model.SourceType) %>
      <%: Html.HiddenFor(model => model.SourceType) %>

This results in this:

      <input id="SourceType" type="hidden" name="SourceType" value="">
      <input id="SourceType" type="hidden" value="11" name="SourceType">
      <input id="SourceType" type="hidden" value="11" name="SourceType">

EDIT: If I exclude the name when not using the helper and used type="text" instead of type="hidden". This renders the value, but doesn't post because it is missing the name (I think).

This:

      <input id="SourceType" type="text" value="<%: Model.SourceType %>" style="visibility: hidden;"/>

Results in this which doesn't bind to the model when posted? How can adding the name affect the value?

      <input id="SourceType" type="text" style="visibility: hidden;" value="11">

EDIT: If anyone can think of something to try I'd love to hear it. I've resorted to an ugly work around involving the addition of a stand in property on the view model. This allows me to set the stand in property value in the controller which renders as expected on the page. On post then I have to manually map the property back the SourceType property. Ugh...

2

There are 2 best solutions below

3
On

Try adding ModelState.Remove("SourceType"); in the controller:

ModelState.Remove("SourceType");
Source source = SourceService.NewSource();
return View("Source", Mapper.Map(source, new SourceViewModel()));

If there is already a value in the ModelState that corresponds to your value, it will use that first. Alternatively, I would double check that the value is mapping correctly to the ViewModel. When you say you checked this, did you check the model itself or just the Source property?

Edit: Try <input id="SourceType" type="hidden" value="<%: Model.SourceType %>" name="SourceType">

0
On

Make sure you don't have an empty querystring parameter by the same property name. HiddenFor appears to prefer what's in the querystring over what's in the model.