What is the difference between Html.Hidden and Html.HiddenFor
Solution 1:
Most of the MVC helper methods have a XXXFor variant. They are intended to be used in conjunction with a concrete model class. The idea is to allow the helper to derive the appropriate "name" attribute for the form-input control based on the property you specify in the lambda. This means that you get to eliminate "magic strings" that you would otherwise have to employ to correlate the model properties with your views. For example:
Html.Hidden("Name", "Value")
Will result in:
<input id="Name" name="Name" type="hidden" value="Value">
In your controller, you might have an action like:
[HttpPost]
public ActionResult MyAction(MyModel model)
{
}
And a model like:
public class MyModel
{
public string Name { get; set; }
}
The raw Html.Hidden
we used above will get correlated to the Name
property in the model. However, it's somewhat distasteful that the value "Name" for the property must be specified using a string ("Name"). If you rename the Name
property on the Model, your code will break and the error will be somewhat difficult to figure out. On the other hand, if you use HiddenFor
, you get protected from that:
Html.HiddenFor(x => x.Name, "Value");
Now, if you rename the Name
property, you will get an explicit runtime error indicating that the property can't be found. In addition, you get other benefits of static analysis, such as getting a drop-down of the members after typing x.
.
Solution 2:
The Html.Hidden creates a hidden input but you have to specify the name and all the attributes you want to give that field and value. The Html.HiddenFor
creates a hidden input for the object that you pass to it, they look like this:
Html.Hidden("yourProperty",model.yourProperty);
Html.HiddenFor(m => m.yourProperty)
In this case the output is the same!
Solution 3:
Every method in HtmlHelper class has a twin with For
suffix.
Html.Hidden takes a string as an argument that you must provide but Html.HiddenFor takes an Expression that if you view is a strongly typed view you can benefit from this and feed that method a lambda expression like this
o=>o.SomeProperty
instead of "SomeProperty" in the case of using Html.Hidden method.
Solution 4:
Html.Hidden('name', 'value') creates a hidden tag with name = 'name' and value = 'value'.
Html.HiddenFor(x => x.nameProp) creates a hidden tag with a name = 'nameProp' and value = x.nameProp.
At face value these appear to do similar things, with one just more convenient than the other. But its actual value is for model binding. When MVC tries to associate the html to the model, it needs to have the name of the property, and for Html.Hidden, we chose 'name', and not 'nameProp', and thus the binding wouldn't work. You'd have to have a custom binding object, or get the values from the form data. If you are redisplaying the page, you'd have to set the model to the values again.
So you can use Html.Hidden, but if you get the name wrong, or if you change the property name in the model, the auto binding will fail when you submit the form. But by using a type checked expression, you'll get code completion, and when you change the property name, you will get a compile time error. And then you are guaranteed to have the correct name in the form.
One of the better features of MVC.
Solution 5:
Html.Hidden and Html.HiddenFor used to generate name-value pairs which waited by action method in controller. Sample Usage(*):
@using (Html.BeginForm("RemoveFromCart", "Cart")) {
@Html.Hidden("ProductId", line.Product.ProductID)
@Html.HiddenFor(x => x.ReturnUrl)
<input class="btn btn-sm btn-warning"
type="submit" value="Remove" />
}
If your action method wait for "ProductId" you have to generate this name in form via using (Html.Hidden or Html.HiddenFor) For the case it is not possible to generate this name with strongly typed model you simple write this name with a string thats "ProductId".
public ViewResult RemoveFromCart(int productId, string returnUrl){...}
If I had written Html.HiddenFor(x => line.Product.ProductID), the helper would render a hidden field with the name "line.Product.ProductID". The name of the field would not match the names of the parameters for the "RemoveFromCart" action method which waiting the name of "ProductId". This would prevent the default model binders from working, so the MVC Framework would not be able to call the method.
*Adam Freeman (Apress - Pro ASP.Net MVC 5)