Mohamed Motaz
Mohamed Motaz

Reputation: 401

What does Html.HiddenFor() actually do?

Html.HiddenFor() is used when I want to persist a field on the page but dont want the user to notice it, like the Id field and such, but does it initialize a value for the Id field? If the Id field already has a value, what does it do then? I am currently taking a course in ASP.Net MVC and I am implementing a controller that both edits and creates new customers. In order to do so, I pass a viewModel to my controller and I check if my Customer object in this viewModel has an Id that isn't equal to 0, if it is equal to 0, then this is a new customer that I need to add to my database, else I need to edit it since it actually is present in my database. So in this case, what does Html.HiddenFor() do? If I remove the Html.HiddenFor() tag from my view, when I am editing a customer, instead of being edited, it creates a new customer. Why is that? The customer I am editing already has an Id which is the key in my database, so how come his Id was treated as 0 in my controller, and so what does Html.HiddenFor() REALLY do? I have seen questions about HiddenFor before and have read the documentation but still cant get what it actually does, especially when there is indeed a field with a value other than 0(the Id field)

My Customer Class:

public class Customer
    {
        public int Id { get; set; }


        [Required] //means that it wont be nullable
        [StringLength(255)] //max len 255 instead of inf 
        public string Name { get; set; }


        public bool IsSubscribedToNewsletter { get; set; }


        [Display(Name = "Membership Type")]
        public MembershipType MembershipType { get; set; }  //navigation property, allows us to navigate from one type to another


        [Display(Name = "Membership Type")]

        public byte MembershipTypeId { get; set; } //foreign key of membership object for optimization purposes
        

        [Display(Name = "Date of Birth")]
        public DateTime? Birthdate { get; set; }  //nullable 
    }

The Save Method in my CustomersController

 [HttpPost]  //make sure not httpget, if modify data, never let it be httpget
        public ActionResult Save(CustomerFormViewModel viewModel) //or use updatecustomerdto (small class we create with only properties we want to update
        {
            if (viewModel.Customer.Id == 0)
            {
                _context.Customers.Add(viewModel.Customer);
            }
            else
            {
                Customer customerInDb = _context.Customers.Single(c => c.Id == viewModel.Customer.Id); //customer object in db
                                                                                                       //need to update its properties to be like those in viemodelcustomer

                //TryUpdateModel(customerInDb,"",new string[] { "Name", "Id" }); //dont use this approach since security conecerns
                //name id is whitelisted as the only things to be updated
                //OR
                //Mapper.Map(customer, customerInDb)

                customerInDb.Name = viewModel.Customer.Name; 
                customerInDb.Birthdate = viewModel.Customer.Birthdate;
                customerInDb.MembershipTypeId = viewModel.Customer.MembershipTypeId;
                customerInDb.IsSubscribedToNewsletter = viewModel.Customer.IsSubscribedToNewsletter;

            }

            _context.SaveChanges(); //must save changes after creating a change in the database

            return RedirectToAction("Index", "Customers");
        }

My CustomerFormView where the Html.HiddenFor element resides in the line before the last one

@model VidlyProject.ViewModels.CustomerFormViewModel

@{
    ViewBag.Title = "New";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>New Customer</h2>

@using (Html.BeginForm("Save", "Customers"))
{
    <!--we surround it in using since beginform creates a <form> tag not </form> so we need to close it afterwards-->
    <div class="form-group">
        <!--bootstrap class for a responsive form-->
        @Html.LabelFor(m => m.Customer.Name) <!--label-->
        @Html.TextBoxFor(m => m.Customer.Name, new { @class = "form-control" }) <!--next paramter is an anonymous object, where each element is rendered as an html attribute-->
        @**\@class not class because class is reserved in c#-->**@
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Customer.Birthdate)
        @*OR <lable for="Birthdate">Date Of Birth</label>*@
                                                    @*format string to format the date *@
        @Html.TextBoxFor(m => m.Customer.Birthdate, "{0: d MMM yyyy}", new { @class = "form-control" })
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Customer.MembershipTypeId)
        @Html.DropDownListFor(m => m.Customer.MembershipTypeId, 
                              new SelectList(Model.MembershipTypes, @*initialize a drop down list*@
                              "Id", @*Name of property in membershiptype class that holds the value for each item*@
                              "Name"), @*Property that holds the text of each item*@
                              "Please select a membership type", @*message at the beginning of the dropdown*@
                              new { @class = "form-control"})
    </div>

    <div class="checkbox">
        <label>
            @Html.CheckBoxFor(m => m.Customer.IsSubscribedToNewsletter, new { @class = "form-check-input" }) Subscribed to the Newsletter?
        </label>
    </div>
    @Html.HiddenFor(c => c.Customer.Id) <!--so that we set an id and the id isnt zero-->
    <button type="submit" class="btn btn-primary">Save</button>
    
}

Upvotes: 0

Views: 859

Answers (1)

Tavershima
Tavershima

Reputation: 141

Let's learn little algorithm here
Assuming you are a receptionist at a hotel and your duty is to report customers in and out of the hotel. Now at your hotel, whenever a customer comes in you request for his registration card. If the customer doesn't have then you know definitely that's his new time coming in. In that case you have to register him as a new user. If he already has, you will then open up his record and mark time in and subsequently time out.
Now a customer comes in claiming he has already been registered. You search the records but the card which he presented was a counterfeit of another which was issued to a different customer or even worse the Id on that card is not in your records. You'll be left with no option than to perform a new registration for that user.

The issue here is this, the user has not presented an Id card or the Id card was false. If you don't put the Html.LabelFor there will be no field to hold the previous Id which was issued to the user

Upvotes: 1

Related Questions