Warm tip: This article is reproduced from stackoverflow.com, please click
asp.net-mvc-5 c# html razor hidden-field

MVC @Html.HiddenFor renders html form with no value

发布于 2020-03-31 22:54:25

Caution, before You read the rest

This question is not about POST method, redisplaying view with submited form or binding input values to controller method parameters. It's purely about rendering the View using html helper (HiddenFor or Hidden - both returns the same).


I created a simple hidden field using HiddenFor helper

@Html.HiddenFor(m => m.ProductCode)

and my problem is that value for this hidden field is rendered as null:

<input id="productCode" name="productCode" type="hidden" value/>

Even if I set it when instantiating a model and of course it's confirmed with debugging (it always has a value).
So instead it should look like this:

<input id="productCode" name="productCode" type="hidden" value="8888888"/>

Because I know there are some questions like this one (actually all of them refer to changing form values during form POST) I included list of things I tried already. My code is right below this section which I belive to be essential.


So far I tried:

  • ModelState.Clear() everywhere possible - cause as we know the value from ModelState is first place where it looks for the value. NO EFFECT which I expected, cause my ModelState is empty (my case is not about changing value during POST in controller as in many questions like that), so it should take value from my view model.
  • Not using HiddenFor helper, but pure html instead. WORKS, but its just workaround, not an answer to the problem.
  • Duplicating line with helper in view as follows:
@Html.HiddenFor(m => m.ProductCode)
@Html.HiddenFor(m => m.ProductCode)

PARTIALLY WORKS Produces first input as value/> and second as value="8888888"/> which indicates that there is probably something that hides initial property value. Anyway, I found nothing in ViewData at any point, nor in query string. Obviously I can't accept it this way, no explonation needed I guess.

  • Changing name of the property. Originally it was ProductCode. I changed it to productCode, ProdCode, ProductCodeasd, etc. and all of these WORKS. Again, it looks like there is something that hides/updates the value, but again - 100% sure there is no JS or anything else doing it. So still no answer found - just workaround again.
  • Explicitly setting the value for HiddenFor: @Html.HiddenFor(x => x.ProductCode, new {Value = @Model.ProductCode}). NO EFFECT, renders the same way.
  • Using @Html.Hidden instead of @Html.HiddenFor. NO EFFECT, with name set as ProductCode it renders the same way.

One more thing I found interesting. Reading html with Display page source in Chrome [ctrl+U] shows that value is valid value="8888888"/>, but in DevTools it's still value/> and of course submitting the form passes null to Controller method.


Model

public class Product
    {
        public string Description { get; set; }
        public int Quantity { get; set; }
        public string ProductCode { get; set; }
        public string ImageUrl { get; set; }

        public Product(string desc, string productCode, string imgUrl)
        {
            Description = desc;
            ProductCode = productCode;
            ImageUrl = imgUrl;
        }
    }

View

@model Product

@using (Html.BeginForm("UpdateCart", "Cart"))
{
    <div class="row pad10">

        <div class="col-sm-6 text-center">
            <img src="@Model.ImageUrl" width="300" height="300" />
        </div>
        <div class="col-sm-6 text-justify">
            <p>@Model.Description</p>
            <div class="row padding-top-2">
                <div class="col-sm-6">
                    <label>@CommonResources.Quantity: </label>
                </div>
                <div class="col-sm-4">
                    @Html.TextBoxFor(m => m.Quantity, new
                    {
                        @class = "form-control",
                        @data_val_required = CommonResources.FieldRequired,
                        @data_val_number = CommonResources.ValidationNumber
                    })
                    @Html.ValidationMessageFor(model => model.Quantity, "", new { @class = "text-danger" })
                    @Html.HiddenFor(m => m.ProductCode)
                </div>
            </div>
        </div>
    </div>
    <div class="text-center col-xs-12 padTop20 padBottom20">
        <input type="submit" value="Submit" class="whtBtn pad" />
    </div>
}

Controller

The view is returned from controller with RedirectToAction as follows:
ValidateAndProceed -> ResolveNextStep (here redirection occurs) -> ShowProduct

        public ActionResult ValidateAndProceed()
        {
            var order = Session.Current.Order;
            var lang = LangService.GetSelectedLanguage();
            var invoice = Session.Current.CurrentInvoice;
            var localCurrency = Session.Current.LocalCurrencyInfo;

            List<CheckoutValidationFieldError> errors = new List<CheckoutValidationFieldError>();

            errors = ValidationService.ValidateAddress(order);
            if (errors.Count > 0)
            {
                return RedirectToAction("InvalidAddress", "Address", new { serializedErrors = JsonConvert.SerializeObject(errors) });
            }

            return ResolveNextStep(order, invoice);
        }

        public ActionResult ResolveNextStep(IOrder order, IInvoice invoice)
        {
            if (OrderService.ShowProductView(order, invoice))
            {
                return RedirectToAction("ShowProduct");
            }
            return RedirectToAction("Summary");
        }

        public ActionResult ShowProduct()
        {
            Product model = ProductService.GetProduct(Session.Current.CurrentInvoice);
            return View("~/Views/Product.cshtml", model );
        }

Finally, what can cause such a weird behavior? I've already ran out of options. Maybe anyone had problem like mine before, would appreciate any clue on this case.

Questioner
Przemysław
Viewed
126
Przemysław 2020-01-31 21:53

I debugged the whole process of rendering the view (got into .Net sources) checking every possible place that could make it fail and found nothing.

After @AndyMudrak and @Jeremy Lakeman comments I decided to try again to find JavaScript responsible for that behavior, but deeper than I did before. What I found was a really silly script where element Id is being concatenated from three strings what I didn't expect, cause it's really badly implemented. So finally - JavaScript is doing it and there is no bad behavior from framework etc.

Actually I am a bit disappointed (even if it's good to know this easy answer) cause it looked much more complicated than it really was and it took me hours to find out how simple it is :|

Thanks for comments, sorry for final simplicity.