mvc3 INT in a IEnumerable selectlistitem - asp.net-mvc-3

I have a selectlistitem that gathers data from the database and inserts it into a dropdownlist. All of that works but I can't seem to make the INT work for instance if I write this.. etc. The issue is with the ArticleID
IEnumerable<SelectListItem> items = db.Articles.Where(c=>c.RegistrationID==getid)
.Select(c => new SelectListItem
{
Value =c.ArticleID +"/"+ c.title,
Text = c.ArticleID + "/" + c.title
});
ViewBag.articles = items;
I get the error Unable to cast the type 'System.Int32' to type 'System.Object' and
then my dropdownlist gets highlighted which is
#Html.DropDownList("article1",(IEnumerable<SelectListItem>)ViewBag.articles)
I obviously can't do c.ArticleID.Tostring() , so how can I fix this issue ? If I take the ArticleID out everything works correctly but I need that in there..

You would actually use c.ArticleID.ToString(). The reason is that you're concatenating a string together, therefore need string values to do so. Value and Text are both string types so it makes sense that you need strings.

Related

Filter SelectListItem value using some condition

I have one SelectListItem for DropDownList. I have to filter based on some condition. If I try adding the condition then its gives me an error like this (LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression). I ll be adding that code here. Please guide me to solve this.
Code
IEnumerable<SelectListItem> IssueId = (from txt in Db.Issues where txt.BibId == BibId
select new SelectListItem()
{
Text = txt.Description,
Value = txt.Id.ToString(),
Selected = true,
});
SelectList IssueIds = new SelectList(IssueId, "Value", "Text");
ViewBag.IssueId = IssueIds;
Thanks
Try this:
LINQ2EF does not know ToString() but after AsEnumerable() you'll get a local collection when ToString() is implemented.
IEnumerable<SelectListItem> IssueId =
(from txt in Db.Issues.Where(e => e.BibId == BibId).AsEnumerable()
select new SelectListItem()
{
Text = txt.Description,
Value = txt.Id.ToString(),
Selected = true
});
Linq To Sql can't generate TSQL for txt.Id.ToString()
You will need to iterate the result instead after executing the query, or cast to Enumerable as xeondev suggests.
That extension does not seem to be sorted by linq to Entities but you could just do the mapping once you have the issues, e.g.
var issues = (from issue in Db.Issues
where issue .BibId == BibId
select issue ).ToList();
IEnumerable<SelectListItem> IssueId = (from txt in issues
where txt.BibId == BibId
select new SelectListItem()
{
Text = txt.Description,
Value = txt.Id.ToString(),
Selected = true,
});

How to Populate ListBoxFor in Mvc3?

I have a list of type stored procedure which have an ID and a Name as data in it.
i have property of int type in model and a list of same stored procedure.
now i want to bind this information into ListBoxFor
in view i have written this
#Html.ListBoxFor(x => x.HobbyId, new MultiSelectList(Model.listHobby, "pkHobbyId", "Hobby"))
but i am getting an error
The parameter 'expression' must evaluate to an IEnumerable when multiple selection is allowed.
Please Help how to bind.
try that
#Html.ListBoxFor(x => x.HobbyId, Model.listHobby.Select(f => new SelectListItem { Text = f.Hobby, Value = f.pkHobbyId.ToString() }), new { Multiple = "multiple" })
listHobby is iEnumerable list on my sample
sorry if i mislead you, rushed to answer but you cannot get the result of the multiselect listbox into a guid or int variable (whatever type is your HoobyId is) you should have an array to grab the result like
public string[] SelectedHobbyIds { get; set; }
so there must be something wrong with your View Models so its better that u would post your view models to be checked
# Chhatrapati Sharma,
In your controller, try this,
ViewData['anyName'] = new SelectList {
Text = , // text from ur function
Value = , // Value from function
Selected = // if required
}
and in view, bind the viewdata like,
<#Html.ListBox("docImages", ((IEnumerable<SelectListItem>)ViewData["anyName"]))
For testing, try a sample selectlist item as follows,
ViewData['anyName'] = new List<SelectListItem>{
new SelectListItem {Text = "First", Value = "0"},
new SelectListItem {Text = "Second"), Value = "1"},
new SelectListItem {Text = "Third", Value = "2"}
};
If this sample works, then check your function "_supp.listDocImages()" and make sure it return IList
#Html.ListBoxFor(x => x.HobbyId, Model.listHobby.Select(f => new SelectListItem { Text = f.Hobby, Value = f.pkHobbyId.ToString() }), new { Multiple = "multiple" })
HobbyId in expression must be ienumerable because you set multi select

Trying to use [Description] data annotation attribute with existing code

SLIGHT UPDATE BELOW
I am trying to use the [Description] data annotation attribute with enums in order to display a friendly name. I've searched around a lot and cannot get anything implemented. Right now I have code that will display an enum as a string (using an extension), but I am not liking ThisIsAnEnum as an enum name (which is spaced out by the string extension) and it prohibits me from having longer names (which I need to maintain) such as for a radio button item. My goal is to have longer descriptions for radio button items without having to write really long enums. An extension/helper will probably be the right way to go, but I need to "fit" it into the code I am using, which is where I failed using the many examples out there.
The code I am using is generic, in that depending upon some logic either a radio button list, check box list, drop down list, select list or regular text boxes are displayed. For multi-item lists enum's are used, and the enum name is what is displayed (after using the string extension).
Here is the particular code that displays the enum:
public static IEnumerable<SelectListItem> GetItemsFromEnum<T>
(T selectedValue = default(T)) where T : struct
{
return from name in Enum.GetNames(typeof(T))
let enumValue = Convert.ToString((T)Enum.Parse(typeof(T), name, true))
select new SelectListItem
{
Text = name.ProperCase(),
Value = enumValue,
Selected = enumValue.Equals(selectedValue)
};
}
ProperCase is the class that changes the enum to something readable.
I found something that almost worked:
public static string GetEnumDescription<TEnum>(TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if ((attributes != null) && (attributes.Length > 0))
return attributes[0].Description;
else
return value.ToString();
}
in which case I changed code from Text = name.ProperCase(), to Text = name.GetEnumDescription(...) but if I put value in the parenthesis I get a "does not exist in the current context" message (which I tried fixing but just made the problem worse). If I leave it blank I get the "No overload for ... takes 0 arguments" (again, understandable - but I don't know how to fix). And if I put name in the parenthesis the code compiles but upon viewing the page I get the "Object reference not set..." error on this line:
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes
(typeof(DescriptionAttribute), false);
I've spent a lot of time on this and know that my stumbling block is the
Text = name.ProperCase(),
code. Any ideas/help? Thanks in advance.
UPDATE:
If I do:
Text = GetEnumDescription(selectedValue),
I actually DO get the [Description] text, however, it just displays for the first enum. So, if I have 5 enums all with different [Description]'s the code just repeats the [Description] for the first enum 5 times instead of displaying differently for each. I hope that makes sense and gets to narrow down the problem.
I'd recommend you the Display attribute:
public static IEnumerable<SelectListItem> GetItemsFromEnum<T>(T selectedValue = default(T)) where T : struct
{
return
from name in Enum.GetNames(typeof(T))
let enumValue = Convert.ToString((T)Enum.Parse(typeof(T), name, true))
select new SelectListItem
{
Text = GetEnumDescription(name, typeof(T)),
Value = enumValue,
Selected = name == selectedValue.ToString()
};
}
public static string GetEnumDescription(string value, Type enumType)
{
var fi = enumType.GetField(value.ToString());
var display = fi
.GetCustomAttributes(typeof(DisplayAttribute), false)
.OfType<DisplayAttribute>()
.FirstOrDefault();
if (display != null)
{
return display.Name;
}
return value;
}
and then you could have:
public enum Foo
{
[Display(Name = "value 1")]
Value1,
Value2,
[Display(Name = "value 3")]
Value3
}
And now you could have:
var foo = Foo.Value2;
var values = GetItemsFromEnum(foo);
Also notice that I have modified the Selected clause in the LINQ expression as yours is not correct.
This being said, personally I would recommend you staying away from enums on your view models as they don't play nicely with what's built-in ASP.NET MVC and you will have to reinvent most of the things.

Why am I getting "Cannot convert lambda expression to type 'string' because it is not a delegate type"?

I have a simple table called LookupTable with two fields: Id (int) and Description (nvarchar) that I want to use to populate a drop down list.
The following code gives me the error:
IEnumerable<SelectListItem> items =
_entities.LookupTable.Select(t=> new SelectListItem {Value = t.Id,
Text = t.Description } );
I have a using System.Linq; statement already, and I get a runtime error if I try t.Id.ToString().
I must be missing something simple, right?
It is not clear from your question what is the type of _entities.LookupTable. If we suppose that it is some IQueryable<SomeModel> or IEnumerable<SomeModel> where SomeModel contains two properties Id and Description, you must ensure that you are properly converting those two values to string as the Value and Text properties of a SelectListItem are strings.
You may also try to eagerly execute the query by calling .ToString():
var items = _entities
.LookupTable
.ToList()
.Select(t => new SelectListItem
{
Value = t.Id.ToString(), // <-- notice that you might need a ToString if the Id property is integer
Text = t.Description
});

ASP.NET MVC3 WebGrid Helper and Model Metadata

I'm trying to use the WebGrid html helper in ASP.NET MVC 3 to autogenerate the columns according to the information found in the ModelMetadata. For example the code in a view that accepts a list of objects would be:
var grid = new WebGrid(Model);
#grid.GetHtml(columns: ViewData.ModelMetadata.Properties.Single.Properties
.Select(p => grid.Column(
columnName: p.PropertyName,
header: p.ShortDisplayName
)));
This actually works like a charm (I was surprised it was that easy actually). What happens here is that from the properties of the model I use the ShortDisplayName as the column's header.
The problem? I need to apply a default format to all columns. Basically I want to use the Html.Raw extension for all the data that my grid will display. An attempt would be something like that :
var grid = new WebGrid(Model);
#grid.GetHtml(columns: ViewData.ModelMetadata.Properties.Single.Properties
.Select(p => grid.Column(
columnName: p.PropertyName,
header: p.ShortDisplayName,
format: (item) => Html.Raw(GetPropertyValue(item, p.PropertyName))
)));
where the method GetPropertyValue would read the value of the property using reflection or whatever (I need to remind here that item is dynamic and its value is actually the object that is being displayed in the current row).
Is there any better way to do this?
Thanks,
Kostas
I suggest you looking into MVCContrib Grid project: http://mvccontrib.codeplex.com/wikipage?title=Grid
Don't know if you still need some help with this question, but I had a problem just like yours and that's what I did to solve it:
I Used a Foreach loop to iterate through the properties
Filled a variable with the name of the property
Formated the column
The code that I got was something like this:
var columns = List<WebGridColumn>();
foreach (var p in ViewData.ModelMetadata.Properties.Single.Properties) {
String propertyName = p.PropertyName;
columns.Add(grid.Column(p.PropertyName, p.ShortDisplayName, format: item => Html.Raw(GetPropertyValue(item.Value, propertyName))));
}
#grid.GetHtml(columns: columns.ToArray());
And that's how I get the property's value:
public static object GetPropertyValue(object obj, String propertyName)
{
if (propertyName.Contains("."))
{
int index = propertyName.IndexOf(".");
object prop = obj.GetType().GetProperty(propertyName.Substring(0, index)).GetValue(obj, null);
return GetPropertyValue(prop, propertyName.Substring(index + 1));
}
return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
}
I really don't know if this is the best way, but it's working pretty good for me.

Resources