0

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>
    
}

Mohamed Motaz
  • 134
  • 1
  • 9
  • You should take a look at this - https://stackoverflow.com/questions/3866716/what-does-html-hiddenfor-do – Sai Gummaluri Aug 01 '20 at 07:42
  • @SaikumarGummaluri I have, and I still dont get why without the HiddenFor method, the Id value is set to 0 even though it originally holds a value – Mohamed Motaz Aug 01 '20 at 07:44
  • 2
    If you don't want to show the element but still want to access it that's what hiddenfor is for. Normally, if you write Label and apply css as display none (forexample), you can neither see the label nor you can access its value. This is where HiddenField comes into action. – noobprogrammer Aug 01 '20 at 07:48
  • So without it, after the object is passed to my view, its like it becomes uninitialized? Like all the object's properties become uninitialized and then only those that I either input from the user or use the HiddenFor method on retain their value? – Mohamed Motaz Aug 01 '20 at 07:51
  • HiddenFields value never becomes uninitialize. When you have a query to fetch the data and if that query has this field which you want to show it as hiddenfield the value gets filled up. – noobprogrammer Aug 01 '20 at 07:59
  • So HiddenField basically keeps my value intact? Because this is the behaviour it displayed, without it, my Id field was 0 rather than its actual value. – Mohamed Motaz Aug 01 '20 at 08:02
  • 1
    Yes HiddenField will keep your value intact provided your query has this field from where you are fetching the value. If the query doesn't have Id your HiddenField won't get filled and you will get 0 instead of any value. – noobprogrammer Aug 01 '20 at 08:05

1 Answers1

1

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

Tavershima
  • 141
  • 8