HTML.HiddenFor value set

135,571

Solution 1

You shouldn't need to set the value in the attributes parameter. MVC should automatically bind it for you.

@Html.HiddenFor(model => model.title, new { id= "natureOfVisitField" })

Solution 2

For setting value in hidden field do in the following way:

@Html.HiddenFor(model => model.title, 
                new { id= "natureOfVisitField", Value = @Model.title})

It will work

Solution 3

Strange but, Try with @Value , capital "V"

e.g. (working on MVC4)

@Html.HiddenFor(m => m.Id, new { @Value = Model.Id })

Update:

Found that @Value (capital V) is creating another attribute with "Value" along with "value", using small @value seems to be working too!

Need to check the MVC source code to find more.


Update, After going through how it works internally:

First of all forget all these workarounds (I have kept in for the sake of continuity here), now looks silly :)

Basically, it happens when a model is posted and the model is returned back to same page.

The value is accessed (and formed into html) in InputHelper method (InputExtensions.cs) using following code fragment

string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));

The GetModelStateValue method (in Htmlelper.cs) retrieves the value as

ViewData.ModelState.TryGetValue(key, out modelState)

Here is the issue, since the value is accessed from ViewData.ModelState dictionary. This returns the value posted from the page instead of modified value!!

i.e. If your posted value of the variable (e.g. Person.Id) is 0 but you set the value inside httpPost action (e.g. Person.Id = 2), the ModelState still retains the old value "0" and the attemptedValue contains "0" ! so the field in rendered page will contain "0" as value!!

Workaround if you are returning model to same page : Clear the item from ModelState,

e.g.

ModelState.Remove("Id"); 

This will remove the item from dictionary and the ViewData.ModelState.TryGetValue(key, out modelState) returns null, and the next statement (inside InputExtensions.cs) takes the actual value (valueParameter) passed to HiddenFor(m => m.Id)

this is done in the following line in InputExtensions.cs

tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName, format) : valueParameter), isExplicitValue);

Summary:

Clear the item in ModelState using:

ModelState.Remove("...");

Hope this is helpful.

Solution 4

It is just Value, not @value.. Try it. I'm not sure about @Model.title, maybe it's just Model.title

Solution 5

Necroing this question because I recently ran into the problem myself, when trying to add a related property to an existing entity. I just ended up making a nice extension method:

    public static MvcHtmlString HiddenFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, TProperty value)
    {
        string expressionText = ExpressionHelper.GetExpressionText(expression);
        string propertyName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expressionText);

        return htmlHelper.Hidden(propertyName, value);
    }

Use like so:

@Html.HiddenFor(m => m.RELATED_ID, Related.Id)

Note that this has a similar signature to the built-in HiddenFor, but uses generic typing, so if Value is of type System.Object, you'll actually be invoking the one built into the framework. Not sure why you'd be editing a property of type System.Object in your views though...

Share:
135,571
arnoldrob
Author by

arnoldrob

Updated on July 09, 2022

Comments

  • arnoldrob
    arnoldrob almost 2 years
    @Html.HiddenFor(model => model.title, new { id= "natureOfVisitField", @value = '@Model.title'})
    

    it doesen't work! how to set the value?

  • der_chirurg
    der_chirurg over 11 years
    @arnoldrob did you try both? It should look like: @Html.HiddenFor(model => model.title, new { id= "natureOfVisitField", Value = '@Model.title'}) or just Model.title at the end.. It runs in my project
  • arnoldrob
    arnoldrob over 11 years
    It's ok but I do a big mistake! Sorry! Thanks
  • Cybercop
    Cybercop about 10 years
    @EdPlunkett why wouldn't it work? Unless you set the value in get method of the controller and send it to the view, it will work perfectly.
  • 15ee8f99-57ff-4f92-890c-b56153
    15ee8f99-57ff-4f92-890c-b56153 about 10 years
    @Biplov13 No foolin', it didn't work. I now think the reason it wasn't working was that my action method wasn't accepting the model as a parameter, or possibly it wasn't attributed with [HttpGet], or something like that. Unfortunately I don't have time to go back right now and recreate it and nail it down.
  • Ortund
    Ortund almost 9 years
    I know I'm more than 2 years late with this, but its important to note that the Html tag rendered with this will have distinct Value and value tags. You want to use value because that's where the controller will look for your data
  • Alexander
    Alexander over 8 years
    No, @Ortund, miss! Other way around, it should start from CAP ;)
  • RitchieD
    RitchieD almost 8 years
    I find this very strange but it seems to be correct. I added the ModelState.Remove("<columnName>") in my controller and my problem went away.
  • David L Morris
    David L Morris over 7 years
    Great catch. This problem took some time and this answer to track down. It concerns me that I may have missed some other subtleties like this elsewhere.
  • David L Morris
    David L Morris over 7 years
    See the answer from @Tejasvi Hegde below for a more complete understanding.
  • levininja
    levininja over 7 years
    This works for me. Using .NET 4.5.2 and ASP.NET MVC 4.
  • AaBa
    AaBa over 7 years
    Value with "V" worked for me, actually very strange! Thank you very much.
  • RoLYroLLs
    RoLYroLLs about 6 years
    still works on MVC 5. caveat: case-sensitive Value
  • Alexander Mihailov
    Alexander Mihailov over 5 years
    The update to this answer should be added to the accepted answer - this insight is invaluable! Thanks a lot for sharing it Tejasvi Hedge!
  • shlgug
    shlgug over 5 years
    Unbelievable. Thanks Tejasvi! In my case the code I added looked like this (this may help someone) ModelState.Remove("Invoice.InvoiceId");
  • Chris
    Chris about 5 years
    Thanks @Cybercop - if you have sent the same model in the get method of the controller was the problem for me, setting the value using hiddenFor wasn't working because the get method's value was persisting (which in my case was null).
  • Markus
    Markus over 4 years
    Another option is to call ModelState.Clear(); instead of explicitly deleting the ID. Of course only if the ModelState does not contain any errors. I call clear when ModelState.IsValid == true and the data has been successfully saved.
  • Canada Wan
    Canada Wan about 4 years
    Invaluable answer, you saved my life! For me I simply replaced Html.HiddenFor(model => model.Id) with <input type="hidden" value="@Model.Id" />. Using @Model.Id instead seems to be more readable than ModelState.Clear().
  • Mariusz Pawelski
    Mariusz Pawelski almost 4 years
    All html helpers in ASP.NET MVC first try to get data from ModelState not from actual Model. It's a long time gotcha that trips up a lot of people. A good explanation why it works that way is this blog weblog.west-wind.com/posts/2012/apr/20/… Arguably it makes less sense for "Hidden" helper, but I guess at least it's consistent with other helpers. As mentioned you can just use model explicitly to render hidden input, like <input id="Id" name="Id" type="hidden" value="@Model.Id" /> instead of clearing model state.