MVC TextBox with name specified not binding model on post

22,186

The first parameter of the HtmlHelper.TextBox function is the name attribute of the input element created by the function. You're specifying "employee_stock_name" as that parameter (and thus as the name attribute of the input element), so that is what is being sent across the wire.

You should either specify the correct name:

@Html.TextBox("EmployeeName", Model.EmployeeName)

or use HtmlHelper.TextBoxFor to generate it automatically:

@Html.TextBoxFor(m => m.EmployeeName)
Share:
22,186
Icestorm0141
Author by

Icestorm0141

C# & .NET developer with a strong focus on CSS & front end web development.

Updated on June 16, 2020

Comments

  • Icestorm0141
    Icestorm0141 almost 4 years

    This is like MVC 101 here so I feel completely helpless on why this isn't working. I have an extremely basic Model:

    public class StockEnrollmentModel
    {
        [Required]
        [DisplayName("Employee Name:")]
        public string EmployeeName { get; set; }
    
    }
    

    My view looks like this:

    @using (Html.BeginForm("SimulateForm", "HR", FormMethod.Post))
    {
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                @Html.LabelFor(e => e.EmployeeName)
                @Html.TextBox("stock_employee_name", Model.EmployeeName)
            </div>
        </div>
    </div>
    <button type="submit" class="btn btn-primary" value="Submit">Submit</button>
    }
    

    The web service I will be posting to requires specific names for the input fields in order to successfully receive the data

    As in, the rendered html needs to read:

    <input type="stock_employee_name" type="text" /> 
    

    After much googling, I determined I need to use an Html.Text box in order to have control of the name attribute that is generated.

    The problem I'm having is that when I submit the form, the model in my controller is completely void of data. Investigating this shows that the form posted to the server with "employee_stock_name=Some Name" rather than "EmployeeName=Some Name"

    From my research, this shouldnt be happening, correct?? This exact situation should be the reason you use TextBox instead of TextBoxFor.

    What am I missing?

    Here is my controller for what its worth:

    [HttpPost]
        public RedirectToRouteResult SimulateForm(StockEnrollmentModel model )
        {
            if ( ModelState.IsValid )
            {
                return RedirectToAction("SignForm", "HR", model);
            }
            return RedirectToAction("StockPurchase", model );
        }
    

    UPDATE

    The accepted answer below was what I eventually ended up using. There's no real way to easily change the name of the HTML field and maintain the MVC model binding. I ended up changing my property names to match what I needed the name field to read.

  • Icestorm0141
    Icestorm0141 almost 9 years
    Again, the rendered html needs to read <input name="employee_stock_name" type="text" />. I've been finding posts where the name of the rendered html field is different from the model property name though. So I wouldnt think this would be a problem. Theres cause for this functionality to exist. What if you want to name your property PersonId but have the query string read Id=? instead?? With those limitations, I should be able to make this work. Why would TextBox exist then if passing in a custom name attribute breaks model binding?
  • Tim
    Tim almost 9 years
    How are you expecting MVC to map employee_stock_name to EmployeeName? And why are you expecting it to be "EmployeeName" if it "needs" to be "employee_stock_name" for your webservice to read it? Edit: Let me add this: What is the name of the property on StockEnrollmentModel that you're expecting to be filled with the value? Also, is that controller/action you showed also the web service you are mentioning? Or are they for some reason two different things?
  • Icestorm0141
    Icestorm0141 almost 9 years
    When I've seen this issue come up in my search results is when you have nested models and your binding to something like: @Html.TextBox("MyPreferedName", Model.SearchParams.someParam) If this isnt what this is supposed to be used for, help me understand why the above code (which was found here: stackoverflow.com/questions/6920935/…) is any different from my use case? How does MVC know how to bind that?
  • Tim
    Tim almost 9 years
    Check my edit on the previous comment and the comment I added to the OP. Something is missing from the discussion, trying to figure out what.
  • Icestorm0141
    Icestorm0141 almost 9 years
    Name of the property on StockEnrollmentModel is EmployeeName. Understandably, its not being filled when the form posts to the controller with "stock_employee_name". The webservice that I am posting to is an external webservice, not that URL. The controller action I have shown is interception and faking out the response the webservice will give. Yes I can alter all my properties, to match the names, but some of the names are pretty obscure and hard to understand. Not ideal
  • Icestorm0141
    Icestorm0141 almost 9 years
    Webservice I'm posting to has corresponding fields that I'm trying to fill. Some of the names are pretty obscure for these fields, so changing my model properties to reflect all the fields the web service is expecting isn't ideal.
  • Tim
    Tim almost 9 years
    So essentially, your question is really "how do I get the MVC binding system to bind a field to a property with a different name [for the purposes of mocking/faking]" is that accurate?
  • Tim Iles
    Tim Iles almost 9 years
    Sorry to say that it sounds like it's grunt work you're just going to have to do - you could probably alleviate it somewhat to use a custom model binder that understands underscore case, but it won't magically resolve stock_employee_name to EmployeeName without a helpful nudge.
  • Icestorm0141
    Icestorm0141 almost 9 years
    That is very accurate