开发者

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:

  1. 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;
        }
    }
    
  2. 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);
    
  3. In view I declare a model:

    @model IEnumerable<dynamic>
    
  4. 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜