MVC ModelBind ListBox With Multple Selections - asp.net-mvc

How do I submit the ListBox selections to the ModelBinder?
<%=Html.Hidden("response.Index",index)%>
<%=Html.ListBox("response[index].ChoiceID",
new MultiSelectList(gc.choice,"ChoiceID","ChoiceText") )%>
'gc.choice' is a List
I can get the fisrt selected value to the model, but not the second selection presumably because I cannot change the index.

I have solved this in a slightly different way...
[Model]
public IEnumerable<string> SelectedStores { get; set; }
[View]
<%= Html.ListBox("SelectedStores",
(MultiSelectList)ViewData["Stores"],
new { size = "8" }) %>
[Controller]
ViewData["Stores"] =
new MultiSelectList(StoreItems, "Value", "Text", model.SelectedStores);
So the model has an IEnumberable that will be populated with the user-selections. The view displays the ListBox with the MultiSelectList and the controller passes in the SelectedStores from the model when it constructs the MultiSelectList.

I built a presentation model SamplePresentationModel class that has a MultiSelect member userList.
Then suppose IEnumerable<User> allUser is the list of options.
I use
View(new SamplePresentationModel(){ userList = new MultiSelectList(allUsers,
"UserId",
"UserName",
allUsers.Select(user => user.UserID))});
to pass the MultiSelection to the view.
Then in the view I can construct the listbox
<label for="userList">users:</label>
<%= Html.ListBox("usersList", Model.userList)%>
In the POST action I can capture the selections:
IEnumerable<int> selectedUserIDs = Request["usersList"].Split(new Char[] { ',' }).Select(idStr => int.Parse(idStr));
Don't know if this helps!

Related

How to Sent selected value DropDownList from View Razor to controller MVC

I have this in the HTTPGET Controller
SelectList ConvenioList = Utilidades.ObtenerConveniosList();
ViewData["ConveniosList"] = ConvenioList;
return View();
In the Razor View I have theses code for represent the list in DropDownList Like this:
#Html.DropDownList("ConveniosList", (IEnumerable<SelectListItem>)ViewData["ConveniosList"], new { #class = "form-control pull-right", #id = "ConvenioId", #style = "color:black;" })
And then The List show it like this in the screen:
DropDownList With Data
I want when a selected one item and summit search button Get the value select in the controller POST like this:
[HttpPost]
public ActionResult Transactions (string rangofecha, [<selected list value>] , string referencia)
{ //do soothing with the values received }
In your View you have this:
#Html.DropDownList("ConveniosList", (IEnumerable<SelectListItem>)ViewData["ConveniosList"], new { #class = "form-control pull-right", #id = "ConvenioId", #style = "color:black;" })
In MVC, model binding is dependent on the name of the element.. and in your case, the name of the dropdownlist is ConveniosList (the first parameter in the DropDownList overload).
So in your controller, where you are binding the values with your action, you need to include the name of the dropdownlist in your parameters like so:
public ActionResult Transactions (string rangofecha, /*[<selected list value>]*/string ConveniosList , string referencia)
The reason why you have to declare ConveniosList as a string is because when you select a value from a dropdownlist.. the value is sent to the controller.. and the value is of type string.
Let me know if this helps.

DropDownList cant get selected values

I'm stucked at creating dropdownlist in ASP.NET MVC.
ViewModel:
public MultiSelectList users { get; set; }
I set the values in controller:
var allUsers = db.Users.Select(u => new {
id = u.UserId,
name = u.Name
}).ToList();
model.users = new MultiSelectList(allUsers, "id", "name");
so selectbox values are set.
In view:
#Html.DropDownListFor(m => m.users, Model.users, new { #class = "form-control" })
The problem is that if I select the value and click submit i get this error:
No parameterless constructor defined for this object.
I think the problem is in the way how I create the dropdownlist in view, I'm not sure how to set it, thanks.
EDIT: If I dont choose any user from dropdown all goes well, but if I choose then the error appears.
You're trying to post to the MultiSelectList property. That's not going to work regardless, but the specific error is related to the fact that MultiSelectList has no parameterless constructor, and there's no way for the modelbinder to new up a class with parameters. Anything involved in the modelbinding process must have a parameterless constructor.
What you should be doing is have an additional property like:
public List<int> SelectedUserIds { get; set; }
And, then bind to that in your view:
#Html.ListBoxFor(m => m.SelectedUserIds, Model.Users)
Also, as you'll notice, I changed DropDownListFor to ListBoxFor. If you're wanting to have a select multiple, you need ListBoxFor.
Looks like it is failing when trying to bind, so to prevent it from binding:
[HttpPost]
public ActionResult YourMethod([Binding(Exclude = "users")] SomeViewModel model)
The post back should go to an IEnumerable to capture the selected items.
Add to view model
public IEnumerable UserList { get; set; }
Change view to
#Html.DropDownListFor(m => m.UserList, Model.users, new { #class = "form-control" })
If you want get selected user id from a dropdownlist you must add a property to your model
public MultiSelectList users { get; set; }
public int SelectedUser { get;set;}
And in view
#Html.DropDownListFor(m => m.SelectedUser, Model.users, new { #class = "form-control" })

MVC Model property resets on page submit

I'm new to MVC so this may sound silly, but here goes: I have a model that contains two lists that need to be passed to an edit form:
public class BaseViewModel
{
public IEnumerable<portal_notifications_types> Types { get; set; }
public IEnumerable<portal_notifications_importances> Importances { get; set; }
}
In the edit form, i Have two dropdownlists for this fields:
#Html.DropDownListFor(m => m.Notification.TypeId, new SelectList(Model.Types, "Id", "Type"), "-- Select type --", new { onchange = "GetNotifType();", style = "width:150px;" })
#Html.DropDownListFor(m => m.Notification.ImportanceId, new SelectList(Model.Importances, "Id", "Importance"), "-- Select importance --", new { style = "width:150px;" })
When I first enter the edit view, everything is ok, the dropdownlists are populated and the corresponding value is selected.
However, when I submit the form, the dropdownlists throw an error, because the Model.Types and Model.Importances lists are null.
How could I overcome this ? I would like to avoid using ViewBag to store those lists, although I know it would work.
Pass the View Model again in your Post Action Method.
[HttpPost]
public ActionResult Index(ViewModel m)
{
return View(m); //Pass the View Model again.
}
You have to repopulate these two SelectLists in the Controller POST method for Edit and again pass the ViewModel in the view for edit. Please share your Controller code for Edit for more details.

SelectList selected value not carried over to DropDownList

I have a Razor page with a drop down list inside a form:
#using (Html.BeginForm("ProductsByOwners", "Report", FormMethod.Post, new { #id = "ProductsByOwners" }))
{
#Html.Label("Choose product owner: ")
#Html.DropDownList("OwnerList", (SelectList)ViewBag.OwnerList, new { #onchange = "this.form.submit();" })
}
The selected value of my SelectList is not being carried over to the DropDownList. I've debugged and stepped through the code and found that (SelectList)ViewBag.OwnerList evaluates properly and has the expected value selected, but the resulting HTML does not have any of the option tags selected.
Can anyone see what I'm doing wrong here?
UPDATED
Here is how the SelectList is created in my action:
ViewBag.OwnerList = new SelectList(ListUtils.ProductOwners(), "Key", "Value", values["OwnerList"]);
The result has the value indicated by values["OwnerList"] selected.
Thanks!
You are not using the DropDownList helper properly. In order to create a dropdownlist you need 2 things:
a scalar property to bind to the selected value when the form is submitted
a collection to bind the options to
In your example you have only one of those 2 things (the second). Your first argument is called OwnerList and you have ViewBag.OwnerList passed as second argument.
So:
#Html.DropDownList(
"SelectedOwnerId",
(SelectList)ViewBag.OwnerList,
new { #onchange = "this.form.submit();" }
)
Obviously I would recommend you using strongly typed views ans view models. And obviously get rid of the weakly typed ViewBag/ViewData/ViewCrap.
So start by designing a view model to meet the requirements of your view (which from what you have shown so far is to display a dropdownlist):
public class OwnerViewModel
{
[DisplayName("Choose product owner: ")]
public string SelectedOwnerId { get; set; }
public IEnumerable<SelectListItem> OwnerList { get; set; }
}
then a controller:
public class ReportController: Controller
{
public ActionResult ProductsByOwners()
{
var model = new OwnerViewModel
{
// preselect the second owner
SelectedOwnerId = "2",
// obviously those come from your database or something
OwnerList = new[]
{
new SelectListItem { Value = "1", Text = "owner 1" },
new SelectListItem { Value = "2", Text = "owner 2" },
new SelectListItem { Value = "3", Text = "owner 3" },
}
};
return View(model);
}
[HttpPost]
public ActionResult ProductsByOwners(OwnerViewModel model)
{
...
}
}
and you have a corresponding strongly typed view:
#model OwnerViewModel
#using (Html.BeginForm("ProductsByOwners", "Report", FormMethod.Post, new { id = "ProductsByOwners" }))
{
#Html.LabelFor(x => x.SelectedOwnerId)
#Html.DropDownListFor(
x => x.SelectedOwnerId,
Model.OwnerList,
new { onchange = "this.form.submit();" }
)
}
The most common reason the selected item is not selected in the DDL is you've named the selectlist the same as the model.
Strongly typed views are preferred, but it's fine to pass the SelectList in a Viewbag. See my tutorial Working with the DropDownList Box and jQuery and my blog Cascading DropDownList in ASP.Net MVC

DropDownListFor in EditorTemplate not selecting value

I have an editor template for a custom object. Inside that editor template I use a couple of DropDownListFor helpers. In each of them I specify a unique model property (with the pre-selected value) and the select list containing all the select options.
Example:
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
I know that the option values are being populated (from viewing source) and that my Model is passed in with the correct ID value (DocumentCategoryType).
When the view is rendered, there is no selected item in my dropdown and therefore it defaults to the first (non-selected) value.
Does anyone have any ideas?
Thanks.
We also solved the solution by populating a new SelectList that has the appropriate SelectListItem selected, but created this extension method to keep the call to DropDownListFor a little cleaner:
public static SelectList MakeSelection(this SelectList list, object selection)
{
return new SelectList(list.Items, list.DataValueField, list.DataTextField, selection);
}
Then your DropDownListFor call becomes:
<%= Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList.MakeSelection(Model.DocumentCategoryType)) %>
Looking through the ASP.NET MVC 2 source code reveals some solutions to this problem. Essentially, any SelectListItem in the SelectList passed in the helper extension method that has the Selected property set to true does not have any bearing over the <option> element rendered with the selected attribute applied for the item.
The selected attribute on <option> elements is determined by
1) checking that the helper extension method was passed a SelectList. If this is null, the framework will look in the ViewData for a value corresponding to the key that is the view model property for which you wish to render the drop down list for. If the value is a SelectList, this will be used to render the <select> including taking any selected values, so long as the model state for the model property is null.
2) If a SelectList has been passed in the helper extension method and the model state for the model property is null, the framework will look in the ViewData for a default value, using the model property name as the key. The value in view data is converted to a string and any items in the SelectList passed to the helper extension method that have a value (if no value is set, then the Text will be checked) that matches the default value will have the Selected property set to true which in turn will render an <option> with the attribute selected="selected".
Putting this together, there are two plausible options that I can see to have an option selected and use the strongly typed DropDownListFor:
Using the following view model
public class CategoriesViewModel
{
public string SelectedCategory { get; private set ; }
public ICollection<string> Categories { get; private set; }
public CategoriesViewModel(string selectedCategory, ICollection<string> categories)
{
SelectedCategory = selectedCategory;
Categories = categories;
}
}
Option 1
Set a value in the ViewData in the controller rendering your view keyed against the property name of the collection used to render the dropdown
the controller action
public class CategoriesController
{
[HttpGet]
public ViewResult Select()
{
/* some code that gets data from a datasource to populate the view model */
ICollection<string> categories = repository.getCategoriesForUser();
string selectedCategory = repository.getUsersSelectedCategory();
CategoriesViewModel model = new CategoriesViewModel(selectedCategory, categories);
this.ViewData["Categories"] = selectedCategory;
return View(model);
}
[HttpPost]
public ActionResult Select(CategoriesViewModel model)
{
/* some code that does something */
}
}
and in the strongly typed view
<%: Html.DropDownListFor(m => m.Categories, Model.Categories.Select(c => new SelectListItem { Text = c, Value = c }), new { #class = "my-css-class" }) %>
Option 2
Render the dropdown using the name of the property of the selected item(s)
the controller action
public class CategoriesController
{
[HttpGet]
public ViewResult Select()
{
/* some code that gets data from a datasource to populate the view model */
ICollection<string> categories = repository.getCategoriesForUser();
string selectedCategory = repository.getUsersSelectedCategory();
CategoriesViewModel model = new CategoriesViewModel(selectedCategory, categories);
return View(model);
}
[HttpPost]
public ActionResult Select(CategoriesViewModel model)
{
/* some code that does something */
}
}
and in the strongly typed view
<%: Html.DropDownListFor(m => m.SelectedCategory, Model.Categories.Select(c => new SelectListItem { Text = c, Value = c }), new { #class = "my-css-class" }) %>
It is confirmed as a bug # aspnet.codeplex.com
and only behaves like this for strongly typed views.
Workaround: populate your SelectList in the view code
like
<%= Html.DropDown("DocumentCategoryType", new SelectList(Model.Categories,"id","Name",Model.SelectedCategory")) =>
Yuck. I ended up solving it like this. I hope this gets fixed for RTM.
<%if(Model!=null){ %>
<%= Html.DropDownListFor(m => m.DocumentCategoryType, new SelectList(Model.DocumentCategoryTypeList,"Value","Text", Model.DocumentCategoryType))%>
<%}else{%>
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
<%}%>
Make sure you have a value assigned to m.DocumentCategoryType when you send it to the view.
Generally this value will get reset when you do a post back so you just need to specify the value
when returning to your view.
When creating a drop down list you need to pass it two values. 1. This is where you will store the selected value 2. Is the actual List
Example
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
I made the mistake of setting the select list item Selected value to True. This won't do anything. Instead just assign a value to m.DocumentCategoryType in your controller and this will actually do the selection for you.
Here's another good solution if the source for your drop down list is an IEnumerable instead of a SelectList:
public static SelectList MakeSelection(this IEnumerable<SelectListItem> list, object selection, string dataValueField = "Value", string dataTextField = "Text")
{
return new SelectList(list, dataValueField, dataTextField, selection);
}
Model.DocumentCategoryTypeList
This is probably your problem. On the SelectListItems, do you set the value to the .ToString() output?
var list = new List<SelectListItem>()
{
new SelectListItem()
{
Value = Category.Book.ToString(),
Text = "Book"
},
new SelectListItem()
{
Value = Category.BitsAndPieces.ToString(),
Text = "Bits And Pieces" },
new SelectListItem()
{
Value = Category.Envelope.ToString(),
Text = "Envelopes" }
};
Works for me after doing that. It just needs to be able to match the value from the object
I managed to solve the same problem by saying the folling:
new SelectList(sections.Select(s => new { Text = s.SectionName, Value = s.SectionID.ToString() }), "Value", "Text")
This trick is converting to the value to a string. I know this has been mentioned in previous answers but i find my solution a little cleaner :). Hope this helps.
Copied na pasted from my project:
<%= Html.DropDownListFor(m => m.Profession.Profession_id, new SelectList(Model.Professions, "Profession_id", "Profession_title"),"-- Profession --")%>
Model that is passed:
...
public Profession Profession { get; set; }
public IList<Profession> Professions { get; set; }
...
Html generated:
<select id="Profession_Profession_id" name="Profession.Profession_id">
<option value="">-- Profesion --</option>
<option value="4">Informatico</option>
<option selected="selected" value="5">Administracion</option>
</select>
Works for me. I have this on the form and the only disadvantage is that if model is not valid and I return the model back to the view I have to reload the list of Professions.
obj.Professions = ProfileService.GetProfessions();
return View(obj);
I also had this problem with a field ProgramName. Turns out we used ViewBag.ProgramName in the BaseController and Layout.cshtml, and this was for a different purpose. Since the value in ViewBag.ProgramName was not found in the dropdownlist, no value was selected even though the SelectListItem.Selected was true for one item in the list. We just changed the ViewBag to use a different key and the problem was resolved.
Here is a drop-in DropDownListFor replacement that varies only slightly from the original MVC source.
Example:
<%=Html.FixedDropDownListFor(m => m.DocumentCategoryType,
Model.DocumentCategoryTypeList) %>
I was worried about the performance of making so many copies of my selectList, so instead, I added the selectedvalue as a custom attribute, then used jquery to actually perform the item select:
#Html.DropDownListFor(item => item.AttendeeID, attendeeChoices, String.Empty, new { setselectedvalue = Model.AttendeeID })
........
jQuery("select[setselectedvalue]").each(function () { e = jQuery(this); e.val(e.attr("setselectedvalue")); });

Resources