I am trying to setup a listboxfor control that is bound to properties on my model. I can populate the listbox correctly but after making selections, the list that should contain the selected items is always empty. What am i doing wrong? I've spent a few hours changing and trying different things but still doesn't work.
----Model----
public class ManagementModel
{
public IEnumerable<SelectListItem> AssignableEntities { get; set; }
public IEnumerable<EntityDT> AssignedTestEntities { get; set; }
}
-----Get method in Controller-----
[HttpGet()]
public ActionResult Index()
{
ManagementModel model = new ManagementModel();
List<SelectListItem> listItems = new List<SelectListItem>();
foreach (EntityDT entity in atomService.GetAllAssignableLocations())
{
SelectListItem item = new SelectListItem()
{
Selected = false,
Text = entity.EntityName,
Value = entity.EntityID.ToString()
};
listItems.Add(item);
}
model.AssignableEntities = listItems;
return View(model);
}
-----View-----
#using (Html.BeginForm("SaveSetup", "Management"))
{
<div>
#Html.ListBoxFor(model => model.AssignedTestEntities, Model.AssignableEntities, new { style = "height:350px;width:175px;" })
</div>
<input type="submit" id="btnGiftManagementSubmit" value="Save" />
}
-----Form Post Method-----
[HttpPost]
[ValidateInput(false)]
public ActionResult SaveSetup(ManagementModel model)
{
The list is empty when it gets to this method
}
I finally figured out this issue. I'll list the steps below for setting these up
The collection property on your model needs to be of type SelectListItem.
The property on your model to store the selected values from the collection need to be string.
That's it and it'll work every time! I've been able to get a few of these working since i figured it out following this method. Good Luck!
Related
I'm trying to generate a DropDownList for each record in a table in a View. I have trouble setting the selected value for the dropdownlist.
In the controller each user's access level list in the model is populated by calling a method in the Repository. I can't seem to get this method quite right. I can change the selected value on item, and accessLevels has correct value selected. But in the view this is not the selected value. How can I set the selected value of a selectlist?
I've tried this:
Repository:
public IEnumerable<SelectListItem> GetSelectListAccessLevelsWithSelectedItem(string selectedAccessLevelID)
{
IEnumerable<SelectListItem> accessLevelsFromDB = DB.AccessLevels
.Select(x => new SelectListItem
{
Value = x.AccessLevelID.ToString(),
Text = x.Name
});
SelectListItem item = null;
foreach (SelectListItem a in accessLevelsFromDB)
{
if (a.Value == selectedAccessLevelID)
{
item = a;
a.Selected = true;
}
}
var accessLevels = new SelectList(accessLevelsFromDB, item.Value);
return accessLevels;
}
And also tried returning accessLevelsFromDB:
return accessLevelsFromDB;
View:
#Html.DropDownList("Accesslevels", user.AccessLevelsWithSelectedItem, new { #class = "form-control", #name = "accessLevels"})
Have I used, SelectList Constructor (IEnumerable, Object), correctly? Or what else am I missing? I have tried to google but still don't understand what I'm doing wrong. I Looked at this question SelectList Selected Value Issue - Stack Overflow but that doesn't seem to work.
Update:
this is the model:
public class EditCustomerViewModel
{
public Customer Customer { get; set; }
public int CustomerID { get; set; }
public List<User> Users { get; set; }
public List<UserToView> UsersToView { get; set; }
public IEnumerable<SelectListItem> AccessLevelListForSelectedUser { get; set; }
}
Update 2:
I've got it working now and have updated my model and repository.
Model:
public class EditCustomerViewModel
{
public Customer Customer { get; set; }
public int CustomerID { get; set; }
public List<UserToView> UsersToView { get; set; }
}
Repository:
public IEnumerable<SelectListItem> GetSelectListAccessLevelsWithSelectedItem(string selectedAccessLevelID)
{
IEnumerable<SelectListItem> accessLevelsFromDB = DB.AccessLevels
.Select(x => new SelectListItem
{
Value = x.AccessLevelID.ToString(),
Text = x.Name,
Selected = x.AccessLevelID.ToString() == selectedAccessLevelID
});
return accessLevelsFromDB;
}
This should give you the selected item for your dropdown:
public IEnumerable<SelectListItem> AccessLevelsWithSelectedItem(string selectedAccessLevelID)
{
return DB.AccessLevels
.Select(x => new SelectListItem
{
Value = x.AccessLevelID.ToString(),
Text = x.Name,
Selected = x.AccessLevelID.ToString() == selectedAccessLevelID
});
}
It would be helpful if we could see the model your view is using. Regardless, you're making this far too difficult.
First, DropDownList needs only IEnumerable<SelectListItem>. Razor will take care of creating a SelectList instance and binding the appropriate selected value. In fact, it does that anyways, which is why your own attempts at selecting an item will be fruitless until you find what's causing the wrong or no value to be bound.
In that regard, everything revolves around ModelState, which is composed of values from Request, ViewBag/ViewData, and finally Model. That "finally" part is important, because anything in the request or view data will always override anything set on your model.
In other words, if your action has a parameter like accessLevels or you're setting something in something like ViewBag.AccessLevels. Those values will be used as the "selected" value for the dropdown.
Again, seeing the view model would be helpful here, but generally speaking, you should be using the *For family of helpers in conjunction with a view model. Ideally, you should have a property on your model like AccessLevels, and then do something like:
#Html.DropDownListFor(m => m.AccessLevels, Model.AccessLevelOptions)
Where AccessLevelOptions would be IEnumerable<SelectListItem> and contain the available access levels. With that, you'll never have any issues with the selected value, because Razor will handle everything and you're strongly bound to a particular property on your model. It's only when you start playing with string names, with no real ties to anything that things start to go awry.
You can just pass in a value attribute of a hardcoded string or the model value for that property:
#Html.DropDownList("Accesslevels", user.AccessLevelsWithSelectedItem, new { #class = "form-control", #name = "accessLevels", Value = "something" })
or
#Html.DropDownList("Accesslevels", user.AccessLevelsWithSelectedItem, new { #class = "form-control", #name = "accessLevels", Value = Model.MyProperty })
I believe this will create a list in my HomeController. But not sure what calls it or where it goes in the Controller beside maybe the first Add ActionResult (GET method).
public static IEnumerable<SelectListItem> items()
{
using (oesacEntities_compact db = new oesacEntities_compact())
{
var query = from s in db.tblSponsors select new { s.SponsorID, s.BizName };
return query.AsEnumerable()
.Select(x => new SelectListItem
{
Value=x.SponsorID.ToString(),
Text = x.BizName
}).ToList();
}
}
I can't seem to send it to the Add view or to reference it from the Add view:
<div class="editor=field">
#Html.DropDownListFor(model => model.SponsorID,IEnumerable<SelectListItem> SelectList);
</div>
It seems so simple in other coding languages. I want to populate a pulldown with about 200 sponsor ID's for value, BizNames for text. For now at least. God help me after that when I want to show an Edit view with the value selected.
thankyou stackoverflow
You need to pass the SelectList to your view. Ideally your view model should include a property for the SelectList but you can (yuk) use ViewBag, for example
View Model
public class MyViewModel
{
public int SponsorID { get; set; }
// other properties
public SelectList SponsorList { get; set; }
}
Controller
public ActionResult SomeThing()
{
MyViewModel model = new MyViewModel();
// assign the select list
var sponsors = from s in db.tblSponsors;
model.SponsorList = new SelecList(sponsors, "SponsorID", "BizName");
return View(model);
}
View
#Html.DropDownListFor(model => model.SponsorID, Model.SponsorList);
or if you assigned the select list to ViewBag
#Html.DropDownListFor(model => model.SponsorID, (SelectList)ViewBag.SponsorList);
In view I have and I am not able to validate the below mvc code
#Html.DropDownList("PriorityId", (IEnumerable<SelectListItem>)#ViewBag.Priority, "--Please Select One--", new { #id = "ddlPriority", #class = "dropdown" })
In Controller I have
private void PriorityDropdownList()
{
IEnumerable<SelectListItem> priorityDropdownlist =_PriorityObj.PriorityDropdownlistGet();
if (priorityDropdownlist != null)
{
ViewBag.Priority = priorityDropdownlist;
}
}
Try to avoid using ViewBag / ViewData for sending data to your view. Use strongly typed views & ViewModels with data annotations as required for validation.
public class CreateIssueVM
{
[Required]
public string Name { set;get;}
public List<SelectListItem> Priorities { get; set; }
[Required]
public int SelectedPriority { set;get;}
}
Here i have decorated the Name and SelectedPriority properties with Required attributes. That means, user needs to enter these, otherwise, it will bring up the validation message of form submit.
In your GET action , set the collection property value and send that to the view.
public ActionResult Create()
{
var vm=new CreateIssueVM();
vm.Priorities =GetPriorities();
return View(vm);
}
Assuming GetPriorities method returns a collection of SelectListItem for the priorities.
public List<SelectListItem> GetPriorities()
{
List<SelectListItem> prioList=new List<SelectListItem>();
prioList.Add(new SelectListItem { Text = "High", Value = "1" });
prioList.Add(new SelectListItem { Text = "Low", Value = "2" });
// to do :read from db and add to list instead of hardcoding
return prioList;
}
Now in our view, which is strongly typed to CreateIssueVM
#model CreateIssueVM
#using(Html.BeginForm())
{
#Html.DropDownListFor(x=>x.SelectedPriority,
new SelectList(Model.Priorities ,"Value","Text"),"select")
#Html.ValidationMessageFor(x=>x.SelectedPriority)
<input type="submit" />
}
When you submit the form, you can check the form is valid or not by checking the ModelState.IsValid property.
[HttpPost]
public ActionResult Create(CreateIssueVM model)
{
if(ModelState.IsValid)
{
// save and redirect
}
vm.Priorities =GetPriorities();
return View(vm);
}
If you want to implement client side validation as well, you may simply include the relevant jquery unobtrusive validation scripts in the view and enable the client side validation in web.config.
I have a List of about 20 items I want to display to the user with a checkbox beside each one (a Available property on my ViewModel).
When the form is submitted, I want to be able to pass the value of each checkbox that is checked back to my controller method via the Selections property on my ViewModel.
How would I go about doing this using the Form Helper class in MVC? Is this even possible?
PS: I don't want a listbox where the user can just highlight multiple items.
Model:
public class MyViewModel
{
public int Id { get; set; }
public bool Available { get; set; }
}
Controller:
public class HomeController: Controller
{
public ActionResult Index()
{
var model = Enumerable.Range(1, 20).Select(x => new MyViewModel
{
Id = x
});
return View(model);
}
[HttpPost]
public ActionResult Index(IEnumerable<MyViewModel> model)
{
...
}
}
View ~/Views/Home/Index.cshtml:
#model IEnumerable<AppName.Models.MyViewModel>
#using (Html.BeginForm())
{
#Html.EditorForModel()
<input type="submit" value="OK" />
}
Editor template ~/Views/Home/EditorTemplates/MyViewModel.cshtml:
#model AppName.Models.MyViewModel
#Html.HiddenFor(x => x.Id)
#Html.CheckBoxFor(x => x.Available)
The best thing to do would be to create a template that can be reused. I have some code at home that I can post later tonight.
Maybe check SO for similar posts in the mean time.
Dynamic list of checkboxes and model binding
This blog post also could help;
http://tugberkugurlu.com/archive/how-to-handle-multiple-checkboxes-from-controller-in-asp-net-mvc-sample-app-with-new-stuff-after-mvc-3-tools-update
Okay i'm new to asp mvc2 and i'm experiencing some problems with the
htmlhelper called Html.dropdownlistfor();
I want to present the user a list of days in the week. And i want the selected item to be bound to my model.
I have created this little class to generate a list of days + a short notation which i will use to store it in the database.
public static class days
{
public static List<Day> getDayList()
{
List<Day> daylist = new List<Day>();
daylist.Add(new Day("Monday", "MO"));
daylist.Add(new Day("Tuesday", "TU"));
// I left the other days out
return daylist;
}
public class Dag{
public string DayName{ get; set; }
public string DayShortName { get; set; }
public Dag(string name, string shortname)
{
this.DayName= name;
this.DayShortName = shortname;
}
}
}
I really have now idea if this is the correct way to do it
Then i putted this in my controller:
SelectList _list = new SelectList(Days.getDayList(), "DayShortName", "DayName");
ViewData["days"] = _list;
return View("");
I have this line in my model
public string ChosenDay { get; set; }
And this in my view to display the list:
<div class="editor-field">
<%: Html.DropDownListFor(model => model.ChosenDay, ViewData["days"] as SelectList, "--choose Day--")%>
</div>
Now this all works perfect. On the first visit, But then when i'm doing a [HttpPost]
Which looks like the following:
[HttpPost]
public ActionResult Registreer(EventRegistreerViewModel model)
{
// I removed some unrelated code here
// The code below executes when modelstate.isvalid == false
SelectList _list = new SelectList(Days.getDayList(), "DayShortName", "DayName");
ViewData["days"] = _list;
return View(model);
}
Then i will have the following exception thrown:
The ViewData item that has the key 'ChosenDay' is of type 'System.String' but must be of type 'IEnumerable<SelectListItem>'.
This errors gets thrown at the line in my view where i display the dropdown list.
I really have no idea how to solve this and tried several solutions i found online. but none of them really worked.
Ty in advance!
I have seen such an error.
This is becouse ViewData["days"] as SelectList is null when the view is rendered. This can be becouse of ViewData["days"] is null or in different type then SelectList.
The problem must be found here:
[HttpPost]
public ActionResult Registreer(EventRegistreerViewModel model)
{
}
Make shure, that this code
SelectList _list = new SelectList(Days.getDayList(), "DayShortName", "DayName");
ViewData["days"] = _list;
runs and that ViewData["days"] not null and IEnumerable before you return View. It must be becouse of Model.IsValid so ViewData["days"] not binded.
The HttpPost controller action will call the model constructor when it sees "EventRegistreerViewModel model".
[HttpPost]
public ActionResult Registreer(EventRegistreerViewModel model)
So if you add code to your EventRegistreerViewModel model like this:
...
public IEnumerable<string> MySelectList { get; set; }
public EventRegistreerViewModel() {
// build the select the list as selectList, then
this.MySelectList = selectList;
}
Then in your view use this code to display the list and the selected item:
Html.DropDownListFor(model => model.ChosenDay, model.MySelectList, "--choose Day--")
This way every time the view model is constructed it will include the select list