Problem with using a ToExpando method
Hi I i try to use a ToExpando solution to use anonymous classes in razor views. I use this solution -> Dynamic Anonymous type in Razor causes RuntimeBinderException
I'll write what i did:
I added a file Extensions.cs where i put following code:
public static class Extensions { public static ExpandoObject ToExpando(this object anonymousObject) { IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject); IDictionary<string, object> expando = new ExpandoObject(); foreach (var item in anonymousDictionary) expando.Add(item); return (ExpandoObject)expand开发者_StackOverflow中文版o; } }
I wrote a query that receive a tuples from database in controller method:
IEnumerable<dynamic> articles = (from p in db.Articles.Where(p => p.user_id == 2) select new { p.article_id, p.title, p.date, p.category, AverageScore = db.Articles_Scores .Where(o => o.user_id == p.user_id && p.article_id == o.article_id) .Average(m => m.score) }).AsEnumerable() .Select(r => r.ToExpando()); int ii = 0; foreach(var it in articles) { // HERE I CAN READ EVERYTHING ii = it.article_id; } return View(articles);
In view I declare a model:
@model IEnumerable<dynamic>
And I try to get every tuples:
@foreach (dynamic item in Model) { // some code @item.article_id // HERE IS EXCEPTION }
In the foreach line I got an Exception:
RuntimeBinderException: 'System.Dynamic.ExpandoObject' does not contain a definition for 'article_id'
What did I do wrong?
You need to call .AsEnumerable()
or .ToList()
first to force ToExpando
to run on the client.
Try:
dynamic articles = (from p in db.Articles.Where(p => p.user_id == 2_
select new
{
p.article_id,
p.title,
p.date,
p.category,
AverageScore = db.Articles_Scores
.Where(o => o.user_id == p.user_id && p.article_id == o.article_id)
.Average(m => m.score)
}).AsEnumerable()
.Select(r => r.ToExpando());
Edit: Make sure you declare dynamic
not var
Edit 2: In your for
look, you're declaring var
again. Change it to:
@foreach (dynamic item in Model) {
// some code
@item.article_id // HERE IS EXCEPTION
}
Ok, building on the first two answers, I added another extension method that I'm surprised I don't see here:
public static List<ExpandoObject> ToExpandoList<T>(this IEnumerable<T> ie) {
return ie.Select(o => o.ToExpando()).ToList();
}
And now in my view I have code like this, and it works just fine using Razor.
var peoples = from f in "tom dick susan roberto".Split(' ')
select new { FirstName = f, Age = f.Length };
ViewBag.People = peoples.ToExpandoList();
The problem is HtmlHelper.AnonymousObjectToHtmlAttributes()
, it's replacing
'_' with '-' for the property name. Look at the comment for the method.
精彩评论