Like this poster, I'm a bit confused by ASP.NET MVC Html.ListBoxFor(...). Specifically I'm putting the selection results in a List but after I post the results I'm getting
InvalidOperationException: The ViewData item that has the key 'SelectedDeclarations' is of type 'System.String[]' but must be of type 'IEnumerable<SelectListItem>'
Here is my abbreviated ViewModel that I'm passing to the strongly-typed razor view
public MyViewModel
{
public MyViewModel()
{
(...)
this.VendorsRequiringDeclaration = new List<SelectListItem>();
this.SelectedDeclarations = new List<String>();
}
public IEnumerable<String> SelectedDeclarations { get; set; }
public List<SelectListItem> VendorsRequiringDeclaration { get; set; }
}
and here is the view code that references them
#Html.ListBoxFor(m=>m.SelectedDeclarations, Model.VendorsRequiringDeclaration, new { #class="editor-field", #size=6})
If I change MyViewModel such that SelectedDeclarations is a List of SelectedListItem rather than a List of String, upon post to the appropriate controller action it thinks my model is invalid:
{"The parameter conversion from type 'System.String' to type 'System.Web.Mvc.SelectListItem' failed because no type converter can convert between these types."}
Ideas? I probably have the wrong LINQ expression for the first parameter, but I can't see it from the similar questions. Thanks in advance!
In the case of ModelState is not valid, you need to reset the ViewData object inside the controller.
Since data inside VendorsRequiringDeclaration is not saved anywhere.
As it turns out the problem was SQL permissions on an underlying data table that I am accessing via EF; the post failed and made it appear to be the Html Helper -- apologies for any confusion!
Based on AlexanderB's suggestion though I did rework the Html.ListBoxFor(...) thusly, and it seems to work fine:
#Html.ListBoxFor(m=>m.SelectedDeclarations,
new MultiSelectList(
Model.VendorsRequiringDeclaration,
"Id",
"VendorName",
Model.VendorsRequiringDeclaration.Select(
x => new SelectListItem()
{
Selected = false,
Text = x.VendorName,
Value = x.Id.ToString()
}).ToList()),
new { #class = "editor-field", #size = 6 } )
Related
MenuType definiation:
public string Code { get; set; }
public string Name { get; set; }
ASP.NET MVC 5
I have searched and read before I'm posting my question here,
I'm trying to LOAD the data in the asp.net mvc dropdownlist why is that so complicated?
//controller
public class ClientController : BaseController
{
public ActionResult Index()
{
List<MenuType> ctypelist = db.ContractTypes.OrderBy(x => x.TypeOfContract).ToList();
IEnumerable<SelectListItem> list = new SelectList(ctypelist.ToList());
ViewBag.DropDownTypeOfContract = list;
return View();
}
}
//html
#model myapp.Models.Client
#Html.DropDownList("Codes", (List<SelectListItem>)ViewBag.DropDownTypeOfContract , new { style = "max-width: 600px;" })%>
What's complicated is that you can't seem to decide which type you're using...
First you have a List<MenuType> (I assume ContractTypes is actually of type MenuType?) Then you create a SelectList, passing the List<MenuType> to it, which implies that MenuType must have at least two properties, one called Text and one called Value. If not, you will have to specify the Text and Value property names in the SelectList constructor parameters.
After that, for some reason you convert it to a IEnumerable<SelectListItem>, then you assign that to a ViewBag item and call your View. So, at this point, your ViewBag.DropDownTypeOfContract is of type IEnumerable<SelectListItem>.
Next, in your View, you for some reason define an #model depite not passing any model at all to the view. Ok.... Whatever...
So now we get to the real problem.
#Html.DropDownList("Codes",
(List<SelectListItem>)ViewBag.DropDownTypeOfContract ,
new { style = "max-width: 600px;" })%>
Ok, let's ignore for a moment the fact that you have a WebForms closing code block indicator (%>) for some reason... The biggest problem here is that you're trying to cast ViewBag.DropDownTypeOfContract to a List<SelectListItem>, which is something it is not, and never was.
You converted the List<MenuType> to a SelectList which you then converted to an IEnumerable<SelectListItem>. There was never any List<SelectListItem> involved.
So, the simple fix (besides rewriting your code to be sane) is to change your cast as such:
#Html.DropDownList("Codes",
(IEnumerable<SelectListItem>)ViewBag.DropDownTypeOfContract,
new { style = "max-width: 600px;" })
EDIT:
Since your MenuType does not contain the appropriate properties, you will have to modify your SelectList as such (Which I mention above). FYI, ctypelist is already a list, no need to convert it to a list again... that's just silly.
IEnumerable<SelectListItem> list = new SelectList(ctypelist, "Code", "Name");
Note: I have posted this answer without knowledge of what variables your MenuType Class has. Please add to your question and I will edit this answer according to youe MenuType Class
All Dropdowns are a collection of Value and Text Pairs.
<select>
<option value=1>TEXT 1</option>
<option value=2>TEXT 2</option>
<option value=3>TEXT 3</option>
</select>
You have a list of List<MenuType>, Which values from the MenuType do you want to display in the DropDown List?
Assuming you have this as MenuType.cs
public class MenuType
{
public int MenuTypeId {get;set;}
public string Name {get;set;}
}
Your dropDown should be generated like this:
public ActionResult Index()
{
Dictionary<int,string> ctypelist = db.ContractTypes.OrderBy(x => x.TypeOfContract).ToDictionary(s => s.MenuTypeId, s=> s.Name);
IEnumerable<SelectListItem> selectListItems = ctypelist.Select(s => new SelectListItem() { Value = s.Key.ToString(), Text = s.Value });
ViewBag.DropDownTypeOfContract = selectListItems;
return View();
}
In View:
#{
var items = (IEnumerable<SelectListItem>) ViewBag.DropDownTypeOfContract;
}
#Html.DropDownList("Codes", items , "Select Item")
I am trying to list the contries in view. I have created a model called tbl_Countries and the code is below
public class tbl_Countries
{
public int ID { get; set; }
public string Country_Name { get; set; }
}
I have a Controller called Home with the following code. I have created an edmx file for TestDB database
public ActionResult Index()
{
TestDBEntities TestdbContext = new TestDBEntities();
var countries = TestdbContext.tbl_Countries.ToList();
return View(countries);
}
Below is my View code
#model IList
displaying the countries using ul li with foreach
If i run the application am getting this error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[TestMVC.tbl_Countries]',
but this dictionary requires a model item of type 'System.Collections.Generic.IList1[TestMVC.Models.tbl_Countries]
I just want to show the list of countries in view and I would like to know
Without creating a model class is it possible to bind grid?
Is it mandatory to specify the model name using #model directive in view?
You got this error 'cause you specified in your view #model List, but pass to it List, try to change it in your view to List
Yes, you can delete #model at all, but in this case your view won't be strongly typed, so you won't be able to use intelli sense
create a list of country type in model
public List< tbl_Countries> country{get;set;}
In index page set the value of this List
public ActionResult Index()
{
TestDBEntities TestdbContext = new TestDBEntities();
tbl_Countries objModel=new tbl_Countries();
objModel.country = TestdbContext.tbl_Countries.ToList();
return View(objModel);
}
According to the error message you are expecting a model of the type List<TestMVC.Models.tbl_Countries> in the view which is different from the List<TestMVC.tbl_Countries> type your action method returns.
To resolve this issue, you could create a list your view expects and map the data you got from Entity Framework to it.
For example:
public ActionResult Index()
{
TestDBEntities TestdbContext = new TestDBEntities();
var countries = new List<TestMVC.Models.tbl_Countries>();
countries = (from country in TestdbContext.tbl_Countries
select new TestMVC.Models.tbl_Countries
{
Country_Name = country.Country_Name
}).toList();
return View(countries);
}
To seperate the logic of the view and data access it is a good practice to have models which are independent from your data models, from the EF models in your example.
First of All Sorry to post the same question thought there are lot of posts already available. I tried all possible ways and finally I dint have any other option other than posting the same question.
I wanted to bind a enum to a DROPDOWNLISTFOR, but the text in a friendly manner. so In the controller I am binding the selectlist like
List<SelectListItem> formTypeSelectList = new List<SelectListItem>();
foreach (FormType type in ItemHelper.EnumToList<FormType>())
{
SelectListItem formTypeList = new SelectListItem();
formTypeList.Text = ItemHelper.GetEnumDescription(type);
formTypeList.Value = Convert.ToString((int)type);
formTypeList.Value = Convert.ToString((int)type);
formTypeSelectList.Add(formTypeList);
}
item.FormTypeSelectListItem = formTypeSelectList;`
My Entity has
public FormType FormType { get; set; }
public List<SelectListItem> FormTypeSelectListItem { get; set; }
public SelectList FinalSelectList
{
get
{
return new SelectList(FormTypeSelectListItem, "Value", "Text", (int)FormType);
}
}
My view has
<%= Html.DropDownListFor(x => x.Item.FormType, Model.Item.FinalSelectList, new { id = "ddlFormType" })%>
I even tried few other option for binding views like
<%= Html.DropDownListFor(x => x.Item.FormType, new SelectListItem(Model.Item.FinalSelectList,"Value","Text",(int)Model.Item.formType)) %>
Nothing works, When I changed to HTML.DropdownList with a name specified it worked perfectly, but i wanted to bind with dropdownlistfor only.
I even tried adding different id, different name in view like
new{id="ddlformType",name="ddlformtype")
nothing worked. Can some one help me to fix this?
Thanks,
Akila
DropDownListFor is looking for an IEnumerable<SelectListItem> for it's items. Try just passing your FormTypeSelectListItem to the DropDownListFor method in place of your FinalSelectList. You may have to cast the model property as an IEnumerable<SelectListItem>
Learning about dropdown lists, Im trying to add a RSVP create page for nerddinner as in Scott Gu's blog with a Html.DropDownListFor listing available dinners.
I can get the dropdown list populated but I cannot get the dropdown to pre select the value ("Sample Dinner 2") I want. Im using an initilizer to seed a few dinner objects in the db. The database is sql ce 4 using a EF 'code first approach'. Sorry I know this is a v common problem and hate to ask, but honestly have spent quite some time on this but cant get it to work:
ViewModel
public class RSVPViewModel
{
public SelectList DinnersList { get; set; }
public RSVP Rsvp { get; set; }
public string SelectedItem { get; set; }
}
Controller
//
//GET: /RSVP/Create
public ActionResult Create()
{
RSVP rsvp = new RSVP();
string selected = "Sample Dinner 2";
var typeList = new SelectList(dbc.Dinners.ToList(), "DinnerID", "Title", selected);
var viewModel = new RSVPViewModel { DinnersList = typeList, Rsvp = rsvp, SelectedItem = selected };
return View("Create", viewModel);
}
View
#Html.DropDownListFor(model => model.Rsvp.DinnerID, Model.DinnersList)
HTML Result
<select data-val="true" data-val-number="The field DinnerID must be a number." data-val-required="The DinnerID field is required." id="Rsvp_DinnerID" name="Rsvp.DinnerID">
<option value="1">Sample Dinner 1</option>
<option value="2">Sample Dinner 2</option>
</select>
So is not preselecting the dropdownlist with the value "Sample Dinner 2" when the page loads. The list displays ok and sets the correct DinnerID when I make a selection and click Submit.
Tries this also:
#Html.DropDownListFor(x => x.SelectedItem, Model.DinnersList)
but doesnt set or bind to Rsvp.DinnerID.
This preselects from the list but doesnt bind (or set Rsvp.DinnerID)
#Html.DropDownList("DinnersList")
I want to keep it mvc3 so want to implement with strong type using ViewModel approach (no ViewData) and preferably using Html.DropDownListFor (not Html.DropDownList).Viewbag seems unnecessary for this case.
Thanks!
Edit1
Thinking I should be using a selectList of selectListItems I tried this verbose approach :
RSVP rsvp = new RSVP();
string selected = "2";
List<SelectListItem> dinners = new List<SelectListItem>();
foreach (Dinner dinner in dbc.Dinners.ToList())
{
SelectListItem slDinner = new SelectListItem();
slDinner.Value = dinner.DinnerID.ToString();
slDinner.Text = dinner.Title;
slDinner.Selected = (slDinner.Value == selected);
dinners.Add(slDinner);
}
var dinnersList = new SelectList(dinners, "Value", "Text", selected);
var viewModel = new RSVPViewModel { DinnersList = dinnersList, Rsvp = rsvp, SelectedItem = selected };
However still no work. Should I be making use of the ViewModel SelectedItem property in: #Html.DropDownListFor.. somehow? Something like :
#Html.DropDownListFor(x => x.SelectedItem, Model.DinnersList)
but how to I get a selected value to set Rsvp.DinnerID. I think thats called binding.
After reading here and here, I finally understand how HtmlDropDownlistFor automatically selects the correct item in the dropdown based on your model - selecting a dinnerID in RSVP (foreign key to dinner.dinnerID) will cause the dropdown containing list of Dinner.DinnerIDs to pre select that value. No need yet I think for selectedValue in the SelectList or ViewModel.
Solution:
//
//GET: /RSVP/Create
public ActionResult Create()
{
//automatically preselects matching DinnerID in the Dinner dropdownlist
var rsvp = new RSVP {DinnerID = 2 };
var typeList = new SelectList(dbc.Dinners.ToList(), "DinnerID", "Title");
var viewModel = new RSVPViewModel { DinnersList = typeList, Rsvp = rsvp};
return View("Create", viewModel);
}
The SelectList constructor you're using is supposed to provide the selected value, but you are providing the selected text. You may want to try:
int selected = 2;
Html.DropDownList only works if the bound property is an int. Any other type, such as a named enum, will cause it to default to the first item.
Add a property to your Model, type int, which wraps the enum you are trying to maintain:
public myEnumType myProperty {get; set;} // don't bind this to Html.DropDownList
public myEnumType myPropertyAsInt {
get {return (int)this.myProperty; }
set {this.myProperty = (myEnumType)value; }
} // bind this instead
No need to use Selected in your SelectList - Html.DropDownList will synchronise just fine.
Please take care if there is a QUERY STRING with same name , it will override that behavior, Not sure about HIDDEN FIELDS with same name.
E.g.
DropDownListFor will use the value of Query String of DinnerID if
found
Html.DropDownList accepts int properties, DropDownListFor too, but you have to be careful what you are doing. I examined the SelectExtensions.cs from ASP.NET MVC 3 and found this:
When you use DropDownList("XyField", "default") to create a DropDown, then you must place the select list into ViewBag.XyField and DropDownList() handles this correctly.
When you use DropDownListFor(m=>m.XyField, ... ), you can pass the select list explictly, like this:
DropDownListFor(m=>m.XyField, ViewBag.XyFieldList as IEnumerable)
When you do this, this following happen:
The second parameter of DropDownListFor(...) will be used as source for the options
If there is a ModelState entry for "XyField", this will be used as the model value
If there is no model state AND Html.ViewData.Eval("XyField") returns not null, this value will be used as the model value.
If the found model value is not null, it will be converted to a string, using CultureInfo.CurrentCulture, and this value is compared with your SelectListItem values to preselect the list options.
Attention here: if you stored your select list in ViewBag.XyField, it will be found before the model is accessed. The don't want to compare "selectList.ToString()" with "selectList[i].Value" to preselect your options. Store your selection list in another place!
The funny thing is, you CAN use DropDownListFor with an implicit select list, in the same way as you expect it from DropDownList(). In this case, you will even store your list in ViewBag.XyField. To make this work, you simply have to call the helper with null as second parameter:
DropDownListFor(m=>m.XyField, null)
Then, the select list is pulled from ViewBag.XyField and step 3 in the list above is skipped. So, if XyField is in the model state, this will take precedence before your own Selected properties in the select list, but otherwise, the select list will be used "as is".
Greetings
Rolf
I am trying to work with an HTML.DropDownList in MVC and am not getting the expected return values. Here is my implementation for the selectList to bind to the drop down -
IEnumerable<status> stat = _provider.GetAllStatuses();
Statuses = new SelectList(stat.ToList(), "id", "name", i.status.id);
And here is my view -
<%= Html.DropDownList("Status",Model.Statuses) %>
I am getting an error when trying to run updatemodel in my controller. I then tried to individually set each object. It turns out that I am not getting a single int from the formvalue as I would expect to. Instead, I am getting a value like "5,10,2,3". I think this is coming from how I set up my selectlist, but I'm not exactly sure. Can anyone see an error in the way I am setting up this dd?
Thanks for any help, and let me know if I can clarify anything.
What does the signature of the post method look like? It (or the model) should have a Status property that's defined as an int. I suspect that you've got more code than you're showing us that is listing all the potential statuses on the page (hidden fields?) and that's what you are seeing posted back as an array of ints.
It should look something like:
public ActionResult PostAction( int status, .... )
{
... status will contain the selected value from the dropdown ...
}
This is how I am doing it:
var stat = _provider.GetAllStatuses();
myViewDataObject.Statuses = new SelectList(stat, "id", "name", i.status.id);
stat is an IEnumerable. Statuses is of type SelectList. You don't need ToList() if you are returning an IEnumerable or IQueryable from your provider.
My view inherits from
System.Web.Mvc.Viewpage<MyProject.Models.MyViewDataClass>
which looks like this:
class MyViewDataClass
{
public int StatusID { get; set; }
public SelectList Statuses { get; set; }
}
In the controller, I am accepting a FormsCollection object, and using the model binder to update it:
public ActionResult Edit(FormCollection collection)
{
var myViewDataObject = new MyViewDataClass();
UpdateModel(myViewDataObject);
}
More info at http://nerddinnerbook.s3.amazonaws.com/Part6.htm