MVC Populating Dropdown from Database - c#

New to MVC trying to populate a dropdown from Database, proving a bit more tricky than I imagined.
Here's what I have.
public class EmployeeDetailsModel
{
public string SelectedEmployee { get; set; }
public IEnumerable<SelectListItem> Employees { get; set; }
}
Controller
public ActionResult MiEmployeeDetails()
{
var model = new EmployeeDetailsModel();
model.Employees = _db.geo_employees.ToList().Select(x => new SelectListItem
{
Value = x.name,
Text = x.name
});
return View(model);
}
View
<%= Html.DropDownListFor(x => x.SelectedEmployee, (SelectList) Model.Employees) %>
But getting the error
CS1963: An expression tree may not contain a dynamic operation

You should not cast your IEnumerable to the SelectList - you need to create a new instance of it:
<%= Html.DropDownListFor(x => x.SelectedEmployee, new SelectList(Model.Employees)) %>
Update. While the comment above holds, the actual problem turned out to be dynamically typed view. Such views do not allow use of lambdas in helpers, such as x => x.SelectedEmployee in question. So the actual solution to the problem was making view strogly typed:
Inherits="System.Web.Mvc.ViewPage<Namespace.EmployeeDetailsModel>

Because Employees is an IEnumerable<SelectListItem>, you don't need to cast it or create a new SelectList(), you can just use it directly.
Also I suspect you are missing a .ToList()
public ActionResult MiEmployeeDetails()
{
var model = new EmployeeDetailsModel();
model.Employees = _db.geo_employees.ToList().Select(x => new SelectListItem
{
Value = x.name,
Text = x.name
}).ToList();
return View(model);
}

ToList should be moved to the end of the statement:
model.Employees = _db.geo_employees.Select(x => new SelectListItem
{
Value = x.name,
Text = x.name
}).ToList();

Related

ArgumentNullException: Value cannot be null. Parameter name: items selectlist .net core

Selectlist works perfectly for Get request .however for Post request it gives null exception
controller code:
var category = _context.CategoryTbl.ToList();
List<SelectListItem> li = new List<SelectListItem>();
li.Add(new SelectListItem { Text = "Select Category", Value = "0" });
foreach (var m in category)
{
li.Add(new SelectListItem { Text = m.Name, Value = m.Id.ToString() });
ViewBag.category =li;
}
View code:
#Html.DropDownListFor(model => model.Category, new SelectList(ViewBag.category, "Value", "Text"), new { #id = "ddlCategory", style = "width: 200px;", #class = "form-control input-lg" })
I'm getting following error :
ArgumentNullException: Value cannot be null. Parameter name: items
Three things:
It's more appropriate to store options as a property on your view model. This gets rid of the problems like this one with dynamics. It's much easier to track down problems when you remain strongly-typed.
You don't need to create a SelectList. All that's need is an IEnumerable<SelectListItem> which you already have.
It's preferable to use the SelectTagHelper here.
Taken together, on your model add:
public IEnumerable<SelectListItem> CategoryOptions { get; set; }
Then in your view:
<select asp-for="Category" asp-items="#Model.CategoryOptions"></select>
It is related to your POST action where you also need a ViewBag.category if you return the same view.
You could either use the way in get method to initial it before return view, or simply use new SelectList(_context.CategoryTbl, "Id", "Name"),refer to below code:
[HttpPost]
public async Task<IActionResult> MyPostMethodName(Model model)
{
if (!ModelState.IsValid)
{
}
//your post logic
//...
//need a ViewBag.category if you return the same view,
ViewBag.category = new SelectList(_context.CategoryTbl, "Id", "Name", model.Category);
return View(product);
}

Cannot change selected value for SelectList - MVC

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 Can't get a DropDownList to populate from table. EF and MVC4

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);

Specific parts of model for drop down list

This is what I'm trying to accomplish.
Basically I have Currency model which contains ID,Name, BuyValue, MidValue, SellValue, and DateCreated.
Now I want to use them in converter I've come up with. It has two drop down lists, where first ddl is From which currency is converted and second To which currency it is converter. Regular stuff.
The first ddl should always contain Name as text in ddl and BuyValue as value, whereas second should always contain Name as text and SellValue as value. Something like this in simple HTML terms.
<select id="ddlFirst">
<option value="BuyValue1">Name1</option>
<option value="BuyValue2">Name2</option>
...
</select>
<select id="ddlSecond">
<option value="SellValue1">Name1</option>
<option value="SellValue2">Name2</option>
...
</select>
Of course this isn't the code for it, it's just clarifying the explanation above.
I'm quite a beginner on this matter, and literally have no clue where to start. What gets me the most is should I somehow separate those values into different models and create a view model out of them or could I just use them somehow. To be honest I'm quite confused so any help is appreciated.
UPDATE
var currencies = db.Currencies.Where(c => c.DateCreated.Equals(today));
var list = currencies.Select(s => new { s.ID, s.Name, s.BuyValue, s.SellValue }).ToList();
var model = new ConverterViewModel
{
FromValues = list.Select( x => new SelectListItem { Value = x.BuyValue.ToString(), Text = x.Name}),
ToValues = list.Select(x => new SelectListItem { Value = x.SellValue.ToString(), Text = x.Name }),
};
This comes up empty though. :( And I know it's not.
What gets me the most is should I somehow separate those values into
different models and create a view model out of them or could I just
use them somehow.
Yes, of course, you should define a view model:
public class MyViewModel
{
public string From { get; set; }
public IEnumerable<SelectListItem> FromValues { get; set; }
public string To { get; set; }
public IEnumerable<SelectListItem> ToValues { get; set; }
}
and then have a controller action populate this view model and pass it to the view:
public ActionResult SomeAction()
{
var currencies = _db.Currencies.ToList();
var model = new MyViewModel
{
FromValues = currencies.Select(x => new SelectListItem { Value = x.BuyValue.ToString(), Text = x.Name }),
ToValues = currencies.Select(x => new SelectListItem { Value = x.SellValue.ToString(), Text = x.Name })
};
return View(model);
}
and finally have a strongly typed view:
#model MyViewModel
<div>
#Html.LabelFor(x => x.From)
#Html.DropDownListFor(x => x.From, Model.FromValues)
</div>
<div>
#Html.LabelFor(x => x.To)
#Html.DropDownListFor(x => x.To, Model.ToValues)
</div>

ASP.Net MVC2 DropDownListFor

I am trying to learn MVC2, C# and Linq to Entities all in one project (yes, I am mad) and I am experiencing some problems with DropDownListFor and passing the SelectList to it.
This is the code in my controller:
public ActionResult Create()
{
var Methods = te.Methods.Select(a => a);
List<SelectListItem> MethodList = new List<SelectListItem>();
foreach (Method me in Methods)
{
SelectListItem sli=new SelectListItem();
sli.Text = me.Description;
sli.Value = me.method_id.ToString();
MethodList.Add(sli);
}
ViewData["MethodList"] = MethodList.AsEnumerable();
Talkback tb = new Talkback();
return View(tb);
}
and I am having troubles trying to get the DropDownListFor to take the MethodList in ViewData. When I try:
<%:Html.DropDownListFor(model => model.method_id,new SelectList("MethodList","method_id","Description",Model.method_id)) %>
It errors out with the following message
DataBinding: 'System.Char' does not contain a property with the name 'method_id'.
I know why this is, as it is taking MethodList as a string, but I can't figure out how to get it to take the SelectList. If I do the following with a normal DropDownList:
<%: Html.DropDownList("MethodList") %>
It is quite happy with this.
Can anyone help?
EDIT: So you are using Entity Framework, yes? In that case with the addition info you put in the comments, you would want to do something like this:
public ActionResult Create()
{
var viewModel = new CreateViewModel(); // Strongly Typed View
using(Entities dataModel = new Entities()) // 'te' I assume is your data model
{
viewModel.Methods = dataModel.Methods.Select(x => new SelectListItem()
{
Text = x.Description,
Value = x.method_id.ToString()
});
}
return View(viewModel);
}
Your strongly typed view model would be:
public class CreateViewModel
{
public string SelectedMethod { get; set; }
public IEnumerable<SelectListItem> Methods { get; set; }
}
Your view code would be:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<CreateViewModel>" %>
<%-- Note the Generic Type Argument to View Page! --%>
<%: Html.DropDownListFor(m => m.SelectedMethod, Model.Methods) %>

Categories