2

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
  • 662
  • 2
  • 9
  • 21
  • Have you tried using `@Html.TextBoxFor` instead of `@Html.TextBox` with custom id? – keenthinker May 20 '15 at 20:08
  • I havent, but as stated, the webservice I am posting to requires the name field to have specified values – Icestorm0141 May 20 '15 at 20:10
  • As initial value or value that should not be changed? – keenthinker May 20 '15 at 20:11
  • As in the rendered html needs to read – Icestorm0141 May 20 '15 at 20:14
  • So it is not about the value, but the name of TextBox control - it should be this specific value? Rename the field in the model class and use TextBoxFor. – keenthinker May 20 '15 at 20:19
  • That code block is the first code block in the post. – Icestorm0141 May 20 '15 at 20:29
  • What web service are you referring to? The only method you have shown is `[HttpPost] SimulateForm(StockEnrollmentModel model)` where the parameter is typeof `StockEnrollmentModel` which has a property named `EmployeeName` so in order for this to bind the textbox **must** be `name="EmployeeName"` –  May 20 '15 at 22:52

3 Answers3

4

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)
Tim
  • 14,999
  • 1
  • 45
  • 68
  • Again, the rendered html needs to read . 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? – Icestorm0141 May 20 '15 at 20:17
  • 1
    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? – Tim May 20 '15 at 20:22
  • 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: http://stackoverflow.com/questions/6920935/control-name-in-textboxfor-in-mvc3) is any different from my use case? How does MVC know how to bind that? – Icestorm0141 May 20 '15 at 20:24
  • 1
    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. – Tim May 20 '15 at 20:26
  • 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 May 20 '15 at 20:29
  • 1
    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 May 20 '15 at 20:35
  • That is very accurate – Icestorm0141 May 21 '15 at 11:43
0

If you really need your html to be rendered as <input name="stock_employee_name" type="text" />, you can add the following attribute to the property on your model: [Bind(Prefix = "stock_employee_name")] - but this is a hack and it sounds like you are misunderstanding a requirement somewhere else? Why does the input name need to be "employee_stock_name"?

Tim Iles
  • 2,232
  • 2
  • 24
  • 26
  • 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. – Icestorm0141 May 20 '15 at 20:31
  • 1
    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. – Tim Iles May 20 '15 at 20:41
0

You can change the name of a rendered textbox from @Html.TextBoxFor by passing in the Name parameter to the htmlAttributes object parameter of the helper method.

@Html.TextBoxFor(model => model.EmployeeName, new { Name = "stock_employee_name" })

This will break your model binding when posting back to your controller but at least your name will be right on the form and the data will get filled when creating the form initially.

You can however, use Request.Form["stock_employee_name"] to retrieve the data in your controller's post Action.

Trucktech
  • 328
  • 1
  • 11