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) %>
Related
I have a model with a foreignkey to another models. From this foreignkey, i want to show into my form a DropDownList with the name of my second models. When i go to create.cshtml or edit.cshtml i have the following error:
ArgumentNullException: Value cannot be null.
Here's my code:
// Models
public class Timesheet
{
public Pharmacy Pharmacy { get; set; }
}
// Controllers / ame code on edit.cshtml.cs
public IActionResult OnGet()
{
Dictionary<int, string> pharmacies = new Dictionary<int, string>();
foreach (Pharmacy p in _context.Pharmacy)
pharmacies.Add(p.PharmacyID, p.Name);
ViewData["PharmacyID"] = pharmacies;
return Page();
}
Into create/edit.cshtml, the HTML are:
#Html.DropDownListFor(model => model.ViewData["PharmacyID"], new SelectList(ViewBag.pharmacies , "key", "value"),"-- select --")
I hope you can help me to fix it :)
Thanks per advance !
The problem is you're binding to ViewData using lambda expression instead of model property with value type and using unassigned ViewBag.pharmacies, hence the binding doesn't work as intended.
You should create a model property first:
[BindProperty]
public int PharmacyID { get; set; }
And then bound it to DropDownListFor helper:
#Html.DropDownListFor(model => model.PharmacyID, new SelectList(ViewData["PharmacyID"], "Key", "Value"),"-- select --")
Or use <select> tag helper:
// Page controller (cshtml.cs)
ViewData["PharmacyID"] = new SelectList(pharmacies, "Key", "Value");
<!-- CSHTML view -->
<select asp-for="PharmacyID" asp-items="#ViewData["PharmacyID"]" ...></select>
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();
I'm trying to create a page where a listbox will contain all my ASP.NET users.
However I'm having a lot of problems attempting to make the Html.Listbox accept the list of users.
I have tried doing this:
<%: Html.ListBox("Membershipusers", Membership.GetAllUsers())%>
and a zillion other approaches that is similar to this. I also have a method on my controller that looks like this:
public ActionResult getAllMembershipUsers()
{
MembershipUserCollection membershipusers = new MembershipUserCollection();
membershipusers = Membership.GetAllUsers();
return View(membershipusers);
}
It seems like it is able to create the list of users, but I still don't know how to show that list in my listbox.
Hope somebody can help me out here.
How about using a view model? Have you tried this approach?
public class UsersViewModel
{
public IEnumerable<string> SelectedUsers { get; set; }
public IEnumerable<SelectListItem> AvailableUsers { get; set; }
}
and then a controller which will populate this view model:
public ActionResult Index()
{
var users = Membership.GetAllUsers().Cast<MembershipUser>();
var model = new UsersViewModel
{
AvailableUsers = users.Select(u => new SelectListItem
{
Value = u.UserName,
Text = u.UserName
})
};
return View(model);
}
and finally in your strongly typed view to the view model
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<UsersViewModel>" %>
...
<%= Html.ListBoxFor(x => x.SelectedUsers, Model.AvailableUsers) %>
I'm creating user control in MVC3 application. My view model looks like that:
public class MyViewModel
{
public object Value { get; set; }
}
The Value property could be an int, string or bool so I can't use [DataType] attribute.
When I create my view model:
var viewModel = new MyViewModel { Value = "" };
or
var viewModel = new MyViewModel { Value = 1 };
I assume that this code:
<%: Html.EditorFor(p => p.Value) %>
should render an HTML input of type textbox. Unfortunately nothing is being rendered.
Everything works fine when I use bool value or some not empty string. Here's an example:
var viewModel = new MyViewModel { Value = true };
Html.EditorFor renders checkbox input:
I did some research, but for now I didn't found solution.
Not a direct answer, but can't you just make your ViewModel generic:
public class MyViewModel<T>
{
public T Value { get; set; }
}
This way, the Html helper method can resolve at compile time exactly what type value is, and exactly which editor to render.
I used:
<%: Html.Editor("Value") %>
instead of:
<%: Html.EditorFor(p => p.Value) %>
and everything works great! The textbox is being rendered for empty string or int value. What is wrong with expression p => p.Value?
Long story short, I'm trying to add a few extra items to ViewData to make my life easier, and its an edge case that doesn't really justify its own model just for this one case. Keep reading for more specific details.
So I have a strongly typed edit view for one of my objects, everything works great until I try to put a dropdownlist on the view with an ID that does not match a property of my class.
I have this
public class MyModel
{
public String Name {get;set;}
public int ID {get;set;}
public MyOtherModel Other {get;set;}
}
public class MyOtherModel
{
public String Name {get;set;}
public int ID {get;set;}
}
I am able to update the Name property.
I'd also like to set the Other.ID property from a DropDownList, but its not letting me do that.
My Controller looks like this
public ActionResult EditView()
{
var da = new DataAccessClass();
var Names = da.ReadActive(); // returns MyOtherModel
var sli = new SelectList(evNames, "ID", "Name");
ViewData["OtherModelNames"] = sli;
return View();
}
My View looks like this:
<p>
<label for="EndTime">Name:</label>
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*")%>
</p>
<p>
<label for="EndTime">Other Name:</label>
<%= Html.DropDownList("OtherNameIDList", (SelectList)ViewData["OtherModelNames"]) %>
<%= Html.ValidationMessage("OtherNameIDList", "*")%>
</p>
I get an error on this line <%= Html.DropDownList("OtherNameIDList", (SelectList)ViewData["Names"]) %>
"There is no ViewData item with the key 'OtherNameIDList' of type 'IEnumerable'."
My expectation is that in the controller action that accepts the POST, I will manually use the FormCollection[] to read out that ID and populate MyOtherModel with the correct ID.
In the controller try:
public ActionResult EditView()
{
var da = new DataAccessClass();
var Names = da.ReadActive(); // returns MyOtherModel
var sli = new SelectList(evNames, "ID", "Name");
ViewData.Add("OtherModelNames", new SelectList("ID", "Name", ""));
return View();
}
The in the view
Html.DropDownList("OtherModelNames")
To get the Other.Id in the dropdownlist, just create a static int in the class:
public static int OtherId {get { return this.Other.Id; }}