Html.DropDownList selected value not working using ViewBag - asp.net-mvc-3

Well, after a couple hours reading stuff over here, trying unsuccessfully all the solutions, also found this article that i thought it would save my life... nothing.
Long story short.
Here is my View (all combinations)
#Html.DropDownList("yearDropDown",(IEnumerable<SelectListItem>)ViewBag.yearDropDown)
#Html.DropDownList("yearDropDownxxx",(IEnumerable<SelectListItem>)ViewBag.yearDropDown)
#Html.DropDownList("yearDropDown",(<SelectList>)ViewBag.yearDropDown)
#Html.DropDownList("yearDropDown")
Here is my Controller
public ActionResult(int year)
{
var years = new int[] { 2007, 2008, 2009, 2010, 2011, 2012 }
.Select(x => new SelectListItem {
Text = x.ToString(),
Value = x.ToString(),
Selected=x==year }).Distinct().ToList();
years.Insert(0, new SelectListItem { Value = null, Text = "ALL YEARS" });
ViewBag.yearDropDown = new SelectList(years, "Value", "Text", years.Where(x => x.Selected).FirstOrDefault());
return View();
}
Here is my rendered HTML. Selected nowhere to be found.
<select id="yearDropDown" name="yearDropDown"><option value="">ALL YEARS</option>
<option value="2007">2007</option>
<option value="2008">2008</option>
<option value="2009">2009</option>
<option value="2010">2010</option>
<option value="2011">2011</option>
<option value="2012">2012</option>
</select>
Needless to mention, but i will, i checked in my Watch and SelectList actually has SelectedValue property populated with the selected year passed to the controller. But when i renders at the view, it goes to the first option.
Please, I need the solution for DropDownList, NOT for DropDownListFor. I am highlighting this because i saw other people here asking for the same help and bunch of people gave them instructions, and almost order them, to use DropDownListFor. There is a reason why i NEED to use DropDownList.
SOLUTION:
Look at my own answer.
However, here are the simple changes i made.
Controller:
ViewBag.yearDropDown = years;
View:
#Html.DropDownList("yearDropDown")

The problem may also be the name, see here.
In the Controller
ViewBag.PersonList= new SelectList(db.Person, "Id", "Name", p.PersonId);
In the View
#Html.DropDownList("PersonList",(SelectList)ViewBag.PersonList )
This will not work, you have to change the name, so it's not the same.
#Html.DropDownList("PersonList123",(SelectList)ViewBag.PersonList )
So change yearDropDown and it Will Work for you.
Best regards
Christian Lyck.

ViewBag.yearDropDown = new SelectList(years, "Value", "Text", years.Where(x => x.Selected).FirstOrDefault());
Last parameter here is SelectListItem, but it must be selected value (string in your example)
SelectList Constructor (IEnumerable, String, String, Object)

I know its an old question, but I will share another solution since sometimes you have done anything correctly, but you can't see the selected value after a request and response, since your razor has bug maybe. In this condition, that I've had, you can use select-option using viewbag:
In controller I had:
ViewBag.MyData = GetAllData(strSelected);
...
and as a private function in controller I had:
private List<SelectListItem> GetAllData(List<string> selectedData)
{
return MyGetAll().Select(x =>
new SelectListItem
{
Text = x.Point,
Value = x.Amount.ToString(),
Selected = selectedPrizes.Contains(x.Amount.ToString())
})
.ToList();
}
And in .cshtml I had:
<select id="Amount" name="Amount" multiple="multiple">
#foreach (var listItem in (List<SelectListItem>)ViewBag.MyData)
{
<option value="#listItem.Value" #(listItem.Selected ? "selected" : "")>
#listItem .Text
</option>
}
</select>
I hope it will be useful for similar problems :)

Change the name of the ViewBag property to NOT match the name of the DropDownList.
Use ViewBag.yearDropDownDD instead of ViewBag.yearDropDown.
ALSO, you are creating the SelectList wrongly.
You need to pass the selected value not the array item:
ViewBag.yearDropDown = new
SelectList(years, "Value", "Text", years.Where(x => x.Selected).FirstOrDefault().Value);

The first place i should've gone to learn.... and i didn't.
Here is my solution
Thank you thou for your answers. Really appreciate it. I feel like shooting my own foot now. Two hours reading blogs and it took me 2 minutes to replicate this example and worked perfectly...

Related

What is default value for "optionLabel" of the HTML DropDownList?

So if Set up a DropDownList where Text: "people names" (string)and Value:studentID (int). in my view like this (assuming myDDL is data from code-behind placed in the viewbag)
#Html.DropDownList("myDDL", (IEnumerable<SelectListItem>)ViewBag.myDDL,
"Select Stuff", new Dictionary<string,object>{
{"class","dropdowns"},{"id","myDDL"}})
What is the value of "Select Stuff" which is an optional label that appears at the beginning of the dropdown list?
I'd like the value because it if no value is selected then I'd like to get all the data.
Thanks!
It's empty and it's always the first option of the dropdown, so make sure that you are binding it to a non-nullable property in the postback action:
<select name="selectedValue">
<option value="">Select Stuff</option>
...
</select>
Also you seem to be using myDDL as both the first argument and the second of the dropdownlist helper which is wrong. The first argument is a property that would be used to get the selected value. The second is the available values and must be an IEnumerable<SelectListItem>.
So something like this would make more sense:
#Html.DropDownList(
"selctedValue",
(IEnumerable<SelectListItem>)ViewBag.myDDL,
"Select Stuff",
new { #class = "dropdowns", id = "myDDL" }
)
But what would really make sense and what I would recommend you is to get rid of this ViewBag and use a view model and the strongly typed version of this helper:
#model MyViewModel
...
#Html.DropDownListFor(
x => x.SelectedValue,
Model.MyDdlItems,
"Select Stuff",
new { #class = "dropdowns", id = "myDDL" }
)
It's the empty string. The documentation covers this (emphasis mine):
optionLabel
Type: System.String
The text for a default empty item.
This parameter can be null.
You can actually try adding a fake value into your List of object inside of your dropdown list which take inn value = "None"/"select stuff" and id = 0. In which it will help you to generate a fake value where user is able to select on the value in the dropdown list and you should be able to handle it on the backend code. Hope this helps.

ViewBag oddity in creating a MultiSelectList

I have spent a lot of time scouring the various forums for help on MultiSelectLists in asp.net MVC3. Finally figured out how to solve my issue now I'm trying to cut down on my code and I've come across something weird with ViewBags. First the code, than I'll explain the behavior.
My function that creates the MultiSelectList to used by the Controller
public MultiSelectList GetPermissionList(string[] selectedValues)
{
List<SelectListItem> permissions = new List<SelectListItem>()
{
new SelectListItem{ Value = "", Text = "None"},
new SelectListItem{ Value = "View", Text = "View"},
new SelectListItem{ Value = "Add", Text = "Add"},
new SelectListItem{ Value = "Edit", Text = "Edit"},
new SelectListItem{ Value = "Delete", Text = "Delete"}
};
return new MultiSelectList(permissions, "Value", "Text", selectedValues);
}
partial code from the edit action from the controller
public ActionResult Edit(int id)
{
ViewBag.Title = "Edit a Security Role";
SecurityRoles securityroles = Repository.Details(id);
ViewBag.Orders = securityroles.Orders.Split(',');
ViewBag.OrdersListBox = GetPermissionList(ViewBag.Orders);
return View(securityroles);
}
partial code from the View
<td class="rightAlign topAlign editor-label">
#Html.MyLabel(m => m.Orders, "lblOrders")
</td>
<td class="editor-field">
#Html.ListBoxFor(m => m.Orders, ViewBag.OrdersListBox as MultiSelectList, new { size = "5" })
</td>
Keep in mind I've cut out a large chunk of code from the edit Action, I have roughly 9 list boxes I'm creating for this security role manager.
My goal, in the edit action is to simply have 1 line of code, calling the GetPermissionList and having it return to the viewbag so I can just display that in the view, as opposed to the 2 lines per listbox that I currently have.
Just looking at the code, it seems obvious if I were to make the call this way:
ViewBag.OrdersListBox = GetPermissionList(securityroles.Orders.Split(','));
It should work, but the selected values do not come through. To compound the oddity, here is something else I tried and it worked fine, but it makes no sense why.
ViewBag.Orders = securityroles.Orders.Split(',');
ViewBag.OrdersListBox = GetPermissionList(securityroles.Orders.Split(','));
ViewBag.Orders plays no role in the ViewBag.OrdersListBox nor is it used in the view, but when I simply assign it a value than the 2nd line of code works.
Does this make sense to anyone? Any suggestions on how to create a way for the GetPermissionList to simply work correctly by sending it a string array instead of passing it the ViewBag object?
I think, You have to set Orders because that is what the selected values are being bound to when the selection happens. You could just pass a string[] if you didn't want to have anything preselected. Check out Darin's answer in this post. He is using a model but i think the same concept applies to view bag.
Multiselect with ViewModel

asp.net helper for DropDownList won't render correctly

I'm attempting to get a dropdown list to select the correct value when the page loads.
#Html.DropDownList("CounterpartyTypeSelect", new SelectList(ViewBag.CounterpartyTypeOptions, "DefaultId", "Value"), new { #class = "selectbox", selected = Model.CounterpartyType })
However, when the page renders it always selects the first value in the dropdown list.
The html source for the page:
<select class="selectbox" id="CounterpartyTypeSelect" name="CounterpartyTypeSelect" selected="977980f2-ebb2-4c2a-92c2-4ecdc89b248d">
<option value="5802239e-c601-4f1e-9067-26321213f6e6">Societa per Azioni (SpA)</option>
<option value="f8160341-4a69-436f-9882-4da31a78f1d5">Gesellschaft mit beshrankter Haftung (GmbH)</option>
<option value="977980f2-ebb2-4c2a-92c2-4ecdc89b248d">Sociedad Anonima (SA)</option>
<option value="cdbeb1d3-301b-4884-b65a-612ddd8306f3">Private Limited Company (Ltd)</option>
<option value="1fe68d96-f31b-4859-9869-8c76a5eb1508">Corporation (Inc)</option>
<option value="9c9e5722-ab59-4d1c-a0a3-91b42a3ee721">Limitada (LTDA)</option>
<option value="0cb57339-8705-4e3a-8f6a-95e9664962b7">Public Limited Company (Plc)</option>
<option value="0924d6f1-06a9-49a3-ac05-b3e2686a0e92">Partnership</option>
<option value="c8fbe021-a8f7-4e9d-ab38-dbeb5af5a631">Limited Liability Company (LLC)</option>
<option value="30d9e22b-34f5-43c5-8471-e614dbedb6a6">Aktiengesellschaft(AG)</option>
</select>
As you can see it is putting the "selected" attribute into the outer select tag instead of on the option that matches the Id. I have another select with identical parameters (except variable names of course) and it renders correctly this way. I do not want to use DropDownListFor<T> because I have a HiddenFor field that actually submits this value in the form and javascript that sets the value to match the Select choice. I've confirmed my database is storing the values that I set correctly. What is going on?
SelectList() has an overload for you to choose the selected item. You are adding it as an HTML attribute in the helper and those get rendered to the parent select tag.
Do this:
#Html.DropDownList("CounterpartyTypeSelect", new SelectList(ViewBag.CounterpartyTypeOptions, "DefaultId", "Value", Model.CounterpartyType), new { #class = "selectbox" })
Use the overload for SelectList that takes four arguments:
new SelectList(IEnumerable items, string dataValueField, string dataTextField, object selectedValue);
What's happening in the first line of your code new { #class = "selectbox", selected = Model.CounterpartyType } is you're providing the selected attribute as an HTML attribute of the parent select element.
So you see selected="977980f2-ebb2-4c2a-92c2-4ecdc89b248d" appearing in your first line of output, which btw doesn't do anything.
Also you're providing the value to search for in the Helper as a hardcoded string "value" instead of the actual value you need from the model. The browser will default to the first option since it can't find any value matching 'value'.
To fix this, provide Model.CounterpartyType as the third parameter to your SelectList parameter instead of 'value'.

How to add new option to drop down list in MVC Razor View?

I have 2 dropdown lists in MVC 3 razor view like this:
#Html.DropDownListFor(m => m.UserGroups, Model.UserGroups.Select(x => new SelectListItem() { Text = x.Name, Value = x.Id }), new { #class="pad5" })
They work fine. I have 3 changes to make -
1) First one needs a new option to be added at the top of this list.
<option value="">--pick--</option>
2) And the second one needs to select a specific option upon load.
Say I want to pre-select this option on my second list.
<option value="100">My Friends</option>
3) both dropdowns have same data source. This causing both list to have same name on the form. How do I change the name?
I am able to change the id, but the name seems not changing if I add this to the end:
new { #id="ViewGroup", #name="ViewGroup"}
If you have a viewmodel created, you can simply do for each dropdown:
#model Namespace.myViewModel
<select id="dropdownOne" name="dropdownOne">
<option value="">--pick--</option>
#foreach (var item in Model.myModel)
{
if(#item.id==100) {
<option value="#item.id" selected="selected">#item.Name</option>
}
else {
<option value="#item.id>#item.Name</option>
}
}
</select>

ASP.NET MVC 3 - Validation Question

Good evening everyone I have a question regarding validation of drop-down list values. I have a view that is bound to a view model type called ReservationData.
This object contains a property CustomerVehicles of type List<VehicleData>. VehicleData has two int properties VehicleMakeId and VehicleModelId.
On my view I am trying to loop over the number of items in the CustomerVehicles collection and displaying two dropdowns for each, a vehicle make dropdown and a vehicle model dropdown using DropDownListFor.
When I try to submit and validate I do not see any validation errors displayed on the screen.
Just in case you are wondering I have added a ValidationMessageFor for each dropdown as well. I am not sure if this is an issue with the structure of my view model and its complexity and how the controls need to be named or how the ids need to be set. Any help would be greatly appreciated.
Here is the code for the looping over the collection:
#for (var i = 0; i < Model.CustomerVehicles.Count(); i++)
{
var vehicleNumber = i + 1;
<div class="vehicle-selection-wrapper">
<div class="content-container">
<h3>
Vehicle #vehicleNumber</h3>
<img class="vehicle-image" alt="manufacturer image" src="#Url.Content("~/Content/images/default-vehicle.gif")" /><br />
#Html.LabelFor(m => m.CustomerVehicles[i].VehicleMakeId)
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
, new SelectList(Model.VehicleMakes, "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption, new { #class = "long-field" })<br />
#Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleMakeId)<br />
#Html.LabelFor(m => m.CustomerVehicles[i].VehicleModelId)
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleModelId
, new SelectList(new List<CWR.Domain.VehicleModel>(), "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption, new { #class = "long-field" })
#Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleModelId)
</div>
</div>
}
Ok so I also noticed that in the generated HTML the selects that are generated are missing the HTML5 data-val attributes that are associated to elements to handle validation. Here is the generated HTML
<select class="long-field" id="CustomerVehicles_0__VehicleMakeId" name="CustomerVehicles[0].VehicleMakeId"><option value="">-- Select --</option>
</select><br />
<span class="field-validation-valid" data-valmsg- for="CustomerVehicles[0].VehicleMakeId" data-valmsg-replace="true"></span><br />
<label for="CustomerVehicles_0__VehicleModelId">Model</label>
<select class="long-field" id="CustomerVehicles_0__VehicleModelId" name="CustomerVehicles[0].VehicleModelId"><option value="">-- Select --</option>
</select>
<span class="field-validation-valid" data-valmsg-for="CustomerVehicles[0].VehicleModelId" data-valmsg-replace="true"></span>
Additionally in my VehicleData class the VehicleMakeId and VehicleModelId properties are decorated with a Required attribute.
UPDATE:
Ok so I was testing and noticed that if I keep my code identical except I swap the Html.DropdownListFor calls with Html.TextboxFor calls then the validation works. What could be causing this? Could it be a framework bug with the unobtrusive validation?
UPDATE: Contains Fix
So after posting this same question on the ASP.NET Forums, I was able to get a solution. In the post you will be able to see that there is a bug in the unobtrusive validation framework and how it handles validation of dropdownlists. The user counsellorben does a good job in explaining the problem as well as a solution (including sample code) that will assist others in avoiding this issue in the future, or at least until Microsoft builds in a fix in to the framework.
Thank you everyone for your assistance.
I too have come across this obviously massive oversight regarding client side validation with dropdownlists in MVC 3 and the best solution I can offer is to put the missing HMTL attributes in yourself.
In your view model create a property like this.
public Dictionary<string, object> CustomerVechicleAttributes
{
get
{
Dictionary<string, object> d = new Dictionary<string, object>();
d.Add("data-val", "true");
d.Add("data-val-required", "Please select a Vechicle.");
return d;
}
}
Then in your code, enter
#Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
, new SelectList(Model.VehicleMakes, "Id", "Name")
, #UIDisplay.Dropdown_DefaultOption,
**Model.CustomerVechicleAttributes** })
Just add the Model.CustomerVechicleAttributes as htmlAttributes to your dropdownlist.
This will inject the necessary attributes that are missing. You will of course need to add any other attributes you may need like your class attribute.
Hope this helps.
This is the simpliest way I found to do it, just adding data-val-*-* attributes in HtmlAttributes of DropDownListFor, inside the view. The following method works with RemoteValidation too, if you do not need remote validation, simply remove the elements containing data-val-remote-*:
#Html.DropDownListFor(m => m.yourlistID, (IEnumerable<SelectListItem>)ViewBag.YourListID, String.Empty,
new Dictionary<string, object>() { { "data-val", "true" },
{ "data-val-remote-url", "/Validation/yourremoteval" },
{ "data-val-remote-type", "POST" }, { "data-val-remote-additionalfield", "youradditionalfieldtovalidate" } })
I hope it may help. Best Regards!
you should try to add data annotations on your view model properties first so you could see the validation messages.
you might find what you need here
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx
or create custom ones if needed.
what exactly do you need to validate?
I had exactly the same problem with the field getting correctly validated in TextBoxFor but not in DropDownListFor.
#Html.DropDownListFor(m => m.PaymentTO.CreditCardType, Model.CreditCardTypeList, "Select Card Type", new { style = "width:150px;" })
Since I had another DropDownListFor working on the same page, I knew that it wasn’t a generic DropDownListFor problem. I also have a complex model and parent object PaymentTO wasn’t initialized. When I set viewTO.PaymentTO = new PaymentTO(); in the Controller, the validation for the DropDownListFor started to work. So there is probably a problem with DropDownListFor, but the fix can be as simple as initializing the object in the controller.

Resources