12

I am working on an ASP.NET MVC-4 web application. I'm defining the following inside my action method to build a SelectList:

ViewBag.CustomerID = new SelectList(db.CustomerSyncs, "CustomerID", "Name");

Then I am rendering my DropDownListFor as follow inside my View:

 @Html.DropDownListFor(model => model.CustomerID, (SelectList)ViewBag.CustomerID, "please select")

As shown I am naming the ViewBag property to be equal to the Model property name which is CustomerID. From my own testing, defining the same name didn't cause any problem or conflict but should I avoid this ?

Winter
  • 3,894
  • 7
  • 24
  • 56
John John
  • 1
  • 72
  • 238
  • 501
  • 1
    Do not do this - it does cause problems (for example you cannot get any client side validation) –  May 11 '16 at 11:26
  • @StephenMuecke clien validation on what? ViewBag doesn't have any validation – teo van kot May 11 '16 at 11:28
  • @teovankot, on the model property `CustomerID` - with OP's usage, there will be no `data-val-*` attributes generated and of the user selects the first "please select" option, no validation error will be displayed (when it should be - assuming `CustomerID` is typeof `int`) –  May 11 '16 at 11:30
  • 2
    @StephenMuecke why i will not get any client side validation .... now i have the customerID as int and it is required. and by default i got a client side validation , that when a user try to submit a form he will get an error that the CustomerID is required... so not sure what do you mean by i cannot get any client side validation ... – John John May 11 '16 at 11:31
  • 1
    Another issue is that if the value of `CustomerID` is set in the controller (i.e. editing and existing entity), it will not selected correctly in the dropdownlist. –  May 11 '16 at 11:31
  • @StephenMuecke why will it not get selected correctly ,, can you advice more?is this realted to using the same name for the viewbag and the model property ? – John John May 11 '16 at 11:34
  • 1
    @StephenMuecke retruning back to the client validation .. now the value for the "please select" will be null,, so the client side validation will still work .. here is the markup – John John May 11 '16 at 11:34
  • @johnG, Refer [this DotNetFiddle](https://dotnetfiddle.net/OxriS9). Note that the value of `ClientID` is set to 2 which matches the 2nd option, yet it is **not** selected in the view –  May 11 '16 at 11:43
  • 1
    @johnG, Note the comment about the validation not working only applies to using `@Html.DropDownList("CustomerID", (SelectList)ViewBag.CustomerID, ....)` –  May 11 '16 at 11:47
  • @StephenMuecke yes i know using DropDownList will not force client side validation.. that why i am using DropdownListfor() .. .. – John John May 11 '16 at 11:50
  • @StephenMuecke so option 2 is not select since the name for the viewbag and the name for the model property is the same ? – John John May 11 '16 at 11:51
  • 1
    @johnG, It will force validation using `DropDownList` if the names are different :) There are 2 ery good reason why you should never use the same nae for the model property and the view bag property. –  May 11 '16 at 11:53
  • @StephenMuecke ok, you right. My appologies – teo van kot May 11 '16 at 11:53
  • If you want get `CustomerID` from dropdown, better use: `@Html.DropDownList("CustomerID", null, "please select")` – SᴇM May 11 '16 at 11:55
  • 2
    @SeM, Absolutely not. You will not get client side validation. –  May 11 '16 at 11:56
  • @StephenMuecke so if i use the following "ViewBag.Customers = new SelectList(db.CustomerSyncs, "CustomerID", "Name")" .. then i use the following "@Html.DropDownListFor(model=>model.CustomerID,(SelectList)ViewBag.Customers, "please select")" .. where i rename my viewbag to be customers .. will it work correctly? – John John May 11 '16 at 11:57
  • @StephenMuecke but you can write your own client side validation in JS, just checking for first parameter (by its index), am I wrong? – SᴇM May 11 '16 at 11:59
  • @johnG, Yes that will work correctly. I will add an answer a bit later explaining the issues and how the methods work internally. –  May 11 '16 at 12:01
  • @StephenMuecke you **will get validation** [check Fiddle](https://dotnetfiddle.net/3fPX6q). But still there is this issue with default selected value – teo van kot May 11 '16 at 12:01
  • @teovankot, As I noted above, the validation issue is when you use the `DropDownList()` method. I'm adding an answer and will update the fiddle showing all use cases –  May 11 '16 at 12:08

2 Answers2

14

You should not use the same name for the model property and the ViewBag property (and ideally you should not be using ViewBag at all, but rather a view model with a IEnumerable<SelectListItem> property).

When using @Html.DropDownListFor(m => m.CustomerId, ....) the first "Please Select" option will always be selected even if the value of the model property has been set and matches one of the options. The reason is that the method first generates a new IEnumerable<SelectListItem> based on the one you have supplied in order to set the value of the Selected property. In order to set the Selected property, it reads the value of CustomerID from ViewData, and the first one it finds is "IEnumerable<SelectListItem>" (not the value of the model property) and cannot match that string with any of your options, so the first option is selected (because something has to be).

When using @Html.DropDownList("CustomerId", ....), no data-val-* attributes will be generated and you will not get any client side validation

Refer this DotNetFiddle showing a comparison of possible use cases. Only by using different names for the model property and the ViewBag property will it all work correctly.

  • Error in fiddle , when i click on submit button . It says "The ViewData item that has the key 'CustomerA' is of type 'System.Int32' but must be of type 'IEnumerable'. " – Saurabh Jul 24 '17 at 08:12
  • @Saurabh, That's because I did not repopulate the `SelectLists` in the POST method before returning the view (as per the GET method) - but that is not the point of the fiddle - its to show that you cannot get correct 2-way binding and/or validation if the same name is used for property your binding to and the `SelectList` (and if you want more details on that error - refer [this question/answer](https://stackoverflow.com/questions/34366305/the-viewdata-item-that-has-the-key-xxx-is-of-type-system-int32-but-must-be-o) –  Jul 24 '17 at 08:16
1

There is not harm to use it. You will not get any error. but best practice is to bind model property.

CrazyDev
  • 157
  • 3
  • 12