.net MVC, SelectLists, and LINQ - asp.net-mvc

I am new to using the Html.DropDownList in the MVC framework and am having a hard time understading how to select the data out my database to bind to the DropDownList. Is there an easy way to return a bindable list (such as a SelectList) from a standard LINQ query?

The SelectList constructor takes an IEnumerable so all you need to do is pass the LINQ query to the constructor like so
var query = from c in customers
select c;
var customerList = new SelectList(query, "CustomerId", "CustomerName");
You should do this in the Controller and have the SelectList in your ViewModel.

You want to use the select keyword in the LINQ query:
var foo = new SelectList(from x in FooRepository.Items
select new SelectListItem { Text = x.Name, Value = x.Id });

var foo = FoorePository.Items.Select(s = > new SelectListItem
{
Text = s.Name, Value = s.Id.ToString()
}
);
Sorry about formatting.

Related

Generic Kendo MVC Grid Used with Different Models

I am trying to use a Kendo Grid generically as a partial view. Kendo requires either a type defined or a datatable to instantiate the grid in a razor view
#(Html.Kendo().Grid<object>() or #(Html.Kendo().Grid(dataTable)
My issue is i want to use the Grid for whatever object, not a specific one.
#(Html.Kendo().Grid<object>()
.Name(Model.MetricName)
.Resizable(resizing => resizing.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.Sortable(sorting => sorting.Enabled(true))
.Pageable(pager => pager.PageSizes(new int[] { 10, 15, 20, 50 }))
.ColumnMenu()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action(Model.MetricName, "AdHocReport", new { metricId = Model.MetricId }))
)
)
by using Object i am able to dynamically load the data returned from the ajax .read method. However the issue is with dates. They are returned in JSON format.
Ive tried this method and I still get JSON string representation of the date
Kendo ASP.NET MVC helper Grid generic class
Is there a way to define the type of grid from a string representation of the type? So lets say i have a string property on the viewModel that is the type of the grid. How can i say Grid ?
ive tried using reflection to instantiate the type but i get the infamous "you are using a variable like a type"
This is driving me nuts... any and all help would be greatly appreciated
So i found the way to make this work and bind correctly and as mentioned above my mrmashal it has to do with using dataTables.
#(Html.Kendo().Grid(Model.GridTable)
here is the viewModel property
public DataTable GridTable { get; set; }
To make this dynamic i use reflection to define the dataTable based upon the properties of a the class i want to populate the grid with
Type elementType = Type.GetType(className, true);
var properties = elementType.GetProperties();
DataTable dataTable = new DataTable();
foreach (PropertyInfo info in properties)
{
dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
}
viewModel.GridTable = dataTable;
However, the key is making sure that the data returned from the AJAX read was a dataTable, not an IEnumerable type.
DataTable dataTable = ToDataTable<AssetLocationHistoryMetricData>(metricData);
var result = dataTable.ToDataSourceResult(request);
and this is what i used to convert the List to a dataTable
public static DataTable ToDataTable<T>(IEnumerable<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
//Get all the properties
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
//Setting column names as Property names
dataTable.Columns.Add(prop.Name);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
//inserting property values to datatable rows
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
//put a breakpoint here and check datatable
return dataTable;
}

How to return distinct data to DropDownListFor?

I apply .Net MVC structure with C#. In the controller, I want to distinct specific column (IndustryName), and return the result to Html.DropDownListFor in view. But I get a running time error at view:
System.Web.HttpException: DataBinding: 'System.String' not include
'IndustryName' property.
Is there any one meet such problem, and how to solve it?
Thank you very much for your helping.
Controller:
public ActionResult Create()
{
var industrys = this._pmCustomerService.GetAll().Select (x => x.IndustryName).Distinct();
ViewBag.Industrys = new SelectList(industrys, "IndustryName", "IndustryName", null);
return View();
}
View:
#Html.DropDownListFor(model => model.IndustryName, (SelectList)ViewBag.Industrys)
Your query is returning IEnumerable<string> (you select only the IndustryName property in the .Select() clause. string does not contain an property named IndustryName so you get this error. Just change the SelectList to
ViewBag.Industrys = new SelectList(industrys);
This will bind the options value and display text to the value of IndustryName
The following sample implementation may help you fix the problem:
var industries= this._pmCustomerService.GetAll()
.GroupBy(ind => new { ind.IndustryName})
.Select(group => new SelectListItem
{
Text = group.First().Name,
Value = group .First().Name
}
);
ViewBag.Industries= industries;
You can find more about the 'GroupBy & Select' approach instead of using linq's Distinct(), here
View
#Html.DropDownList("ddlIndustries",(#ViewBag.Industries) as IEnumerable<SelectListItem>)
If you like to use DropDownListFor helper instead then modify view code as follows:
#{
var industries = ViewBag.Industriesas IEnumerable<SelectListItem>;
}
#Html.DropDownListFor(m=> industries , industries )
You get this error because you create SelectList with wrong collection. This should work i think.
var industrys = this._pmCustomerService.GetAll().Select(x => new SelectListItem
{
Value = x.IndustryName,
Text = x.IndustryName
}).Distinct();
ViewBag.Industrys = new SelectList(industrys);
return View();
You are only Selecting IndustryName which is obviously of type String, use DistinctBy() from MoreLinq by Jon Skeet, here is the reference SO post:
public ActionResult Create()
{
var industrys = this._pmCustomerService.GetAll().DistinctBy(x => x.IndustryName);
ViewBag.Industrys = new SelectList(industrys, "IndustryName", "IndustryName", null);
return View();
}

Issues converting types to new selectitemlist

vs'12 asp.net C# MVC4 EF code first
in the controller
var usernames = Roles.GetUsersInRole("Admin");
var adminUsers = db.UserProfiles
.Where(x => !usernames.Contains(x.UserName)).ToList();
List<UserProfiles> myList = adminUsers.ToList();
IEnumerable<UserProfiles> myEnumerable = myList;
ViewBag.DDLRoles = myEnumerable;
The error coming into the view states
The ViewData item that has the key 'DDLRoles' is of type 'System.Collections.Generic.List'1[[OG.Models.UserProfiles, OG, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' but must be of type 'IEnumerable<SelectListItem>'.
And i have been trying to convert this query to IEnumerable<SelectListItem> like crazy, If anyone can help me convert this the right way i'd appreciate it alot.
Also if i did not make it clear, what I'm doing is taking a list of users from the linq query that are NOT of "Admin" Roles and I am trying to display them inside of a DropDrownList
EDIT: the view
#model OG.Models.UserProfiles
then later
#Html.DropDownList("DDLRoles", (SelectList)ViewData["SelectedValue"])
Your View should be like this:
#model OG.Models.UserProfiles
#Html.DropDownListFor(model => model.UserID, new SelectList(ViewBag.DDLRoles, "UserID", "UserName", Model.UserID))
And, in your Controller, you'll have:
var usernames = Roles.GetUsersInRole("Admin");
var adminUsers = db.UserProfiles
.Where(x => !usernames.Contains(x.UserName)).ToList();
ViewBag.DDLRoles = adminUsers;
This will submit the UserID of the selected user from the DropDownList to your Action. By the way, please choose more meaningful names for your Models. Your "UserProfiles" Model should be called "UserProfile" or "User", because it represents one User only, not a collection of Users.
The second parameter needs to be an IEnumerable<SelectListItem>, something like this:
#{
List<UserProfiles> Users = ViewBag.DDLRoles;
}
#Html.DropDownList("Users", Users.Select(x => new SelectListItem() { Text = x.UserName, Value = x.UserName }));

Can I customise my data text field in an MVC SelectList for use with the HtmlHelper.DropDownList without having to create a new struct or class?

I am creating a SelectList from a List(T) class to use to populate a HtmlHelper.DropDownList in an MVC view, setting the dataValueField and dataTextField in the Select List constructor. The text that should be displayed doesn't excatly match one of the properties on my class and still needs to be manipulated. Is there any way of doing this through the SelectList constructor? I realise I could do this by creating a struct or class to use as the IEnumerable input for the Select list but I'd prefer not if I don't need to.
My Controller code is currently:
var members = MemberService.GetAll();
this.ViewData["Members"] = new SelectList(members, "Id", "Name");
My View code is currently:
<%= Html.DropDownList("Members") %>
Instead of "Surname" as my display field I'd like to be able to preformat the field by combining (and formatting) two properties.
You can create loop through the members list, adding the values to a new list that you then create the SelectList from. Something like:
var members = MemberService.GetAll();
List<object> newList = new List<object>();
foreach(var member in members)
newList.Add( new {
Id = member.Id,
Name = member.Name + " " + member.Surname
} );
this.ViewData["Members"] = new SelectList(newList, "Id", "Name");
I can't remember if you can use an anonymous type like that or not, but if not you can create an small data class to use as an intermediary.
You can create an extension method and set whatever you want as the text. It could be something as
public static IList<SelectListItem> ToSelectList<T>(this IEnumerable<T> itemsToMap, Func<T, string> textProperty, Func<T, string> valueProperty, Predicate<T> isSelected)
{
var result = new List<SelectListItem>();
foreach (var item in itemsToMap)
{
result.Add(new SelectListItem
{
Value = valueProperty(item),
Text = textProperty(item),
Selected = isSelected(item)
});
}
return result;
}
Then you call this method as:
var membersSelectList = MemberService.GetAll().ToSelectList(m=>m.FirstName + " " + m.Surname, m.Id.ToString(), m=>m.Id < -1); //Any predicate you need here.
For those that use LINQ.
Instead of:
var members = MemberService.GetAll();
you can use:
ViewBag.MembersList = new SelectList(
from x in db.members where x.role = 5 select new {x.ID, x.Name, x.Surname, S_Name = x.Surname + " " + x.Name},
"ID", "S_Name");
and then use ViewBag.MemberList in your Razor code like
#Html.DropDownList("MembersList", String.Empty)

Adding a default SelectListItem

public IEnumerable<SelectListItem> GetList(int? ID)
{
return from s in db.List
orderby s.Descript
select new SelectListItem
{
Text = s.Descript,
Value = s.ID.ToString(),
Selected = (s.ID == ID)
};
}
I return the above to a view and populate a DropDownList. I would like to add a default SelectListItem (0, "Please Select..") to the above linq result before it is returned to the view. Is this possible?
return new[] { new SelectListItem { Text = ... } }.Concat(
from s in db.List
orderby s.Descript
select new SelectListItem
{
Text = s.Descript,
Value = s.ID.ToString(),
Selected = (s.ID == ID)
});
As you are using ASP.NET MVC, you can do this in the view by specifying a value for the optionLabel parameter of the DropDownField method of the HtmlHelper - e.g:
htmlHelper.DropDownList("customerId", selectList, "Select One");
Putting this type of code in your UI layer is probably more appropriate than having it in the data layer. One downside to doing this is that your select box will have an empty string value, not a "0" for the 'Select One' option, but that is not really a problem as you can treat this as a null value if your controller action method can accept a nullable int for the relevant parameter - e.g.
public ActionResult DoSomething(int? customerId)
{
if(customerId != null)
{
// do something with the value
}
}
var list = from s in db.List
orderby s.Descript
select new SelectListItem
{
Text = s.Descript,
Value = s.ID.ToString(),
Selected = (s.ID == ID)
};
list.Insert(0, new SelectListItem { Text = "Please Select...", Value = string.Empty });
return list;
firt put your default value in the list
list.add(your default list item)
and then do list.addrange(linq select query)
cheers
Here is what I did, I read my values from an XML file into an IList. I then inserted a new record into the IList at position 0. Then make a select list from the IList.
IList< MY_DATA > mydata = (from tmp in myXML.Descendants("R").ToList()
select new MY_DATA
{
NR = tmp.Attribute("NR").Value,
NA = tmp.Attribute("NA").Value
}).ToList<MY_DATA>();
mydata.Insert(0, new My_DATA() { NR = "", NA = "--Click to Select--" });
SelectList mylist = new SelectList(mydata, "NR", "NA");
After I reviewed many questions, and I don't find what i'm looking for.I don't need many lines of code to just have a simple drowpdown. so I want to share with you what I use and it easy and simple.. ( specially if you don't want to use and Entity Framework..
using System.Web.Mvc;
SelectList(IEnumerable items, string dataValueField, string dataTextField);
For Example:
in Controller add :
SelectList slTitle = new SelectList(Query.SelectAllTitle(), "TitleID", "TitleName");
ViewBag.TitleSelectList = slTitle;
in View add :
#Html.DropDownList("TitleSelectList", "--please select--")
This is just for people who are using Webpages framwork (not MVC and webform) with Razor V2 and C#, you need do
#Html.DropDownList("category", "Please select", listData)
Note: OptionalLabel need to be the middle parameter.
Equivalent would be add a SelectListitem to your list data:
var list=db.Query("select id, name from dbtable");
List<SelectListItem> listData = new List<SelectListItem>();
listData.Add(new SelectListItem
{
Text = "Please select",
Value = "",
});
foreach(var item in list) {
listData.Add(new SelectListItem {
Text = item.Name,
Value = item.id,
Selected = isSelected
});
}
#Html.DropDownList("play" , listData)

Resources