Хранение анонимного объекта в ViewBag - PullRequest
19 голосов
/ 24 января 2012

Это, вероятно, глупый вопрос, но я пытаюсь вставить анонимный объект в ViewBag, например, так:

ViewBag.Stuff = new { Name = "Test", Email = "user@domain.com" };

и получить к нему доступ из вида следующим образом:

@ViewBag.Stuff.Name

Я понимаю, что ViewBag является динамическим, и что "Stuff" - это анонимный объект ... но когда я смотрю с отладчиком из строки View выше, я вижу все свойства с правильными значениями. Почему связующему модели так тяжело с этим?

Есть ли хороший способ сделать это без создания модельного класса? Я хочу продолжать использовать new {}

Ответы [ 4 ]

8 голосов
/ 24 января 2012

По сути, проблема в том, что анонимные типы генерируются как внутренние ( см. Ответ ), что делает невозможным типизированные ссылки на свойство объекта из представления. Эта статья предоставляет более подробное объяснение:

http://www.heartysoft.com/anonymous-types-c-sharp-4-dynamic

Это возможно сделать с помощью класса-оболочки Dynamic Anonymous (ответ @ Dakill), но он становится ужасно быстрым и должен задавать вопрос программисту, почему он / она так поступил.

5 голосов
/ 24 января 2012

Вопреки распространенному мнению, это может быть сделано, но включает в себя несколько уродливый хак, который приведет к проблемам с обслуживанием в будущем. Он включает в себя написание класса, который «обернет» ваш анонимный объект в динамический объект. Некоторое время назад я сделал это в качестве упражнения, ниже приведен код класса-оболочки, вы можете использовать его как ViewBag.Stuff = new DynamicAnonymous(new { Name = "Test", Email = "user@domain.com" }); ..

public class DynamicAnonymous : DynamicObject
{
            object obj;

            public DynamicAnonymous(object o)
            {
                    this.obj = o;
            }

            public override IEnumerable<string> GetDynamicMemberNames()
            {
                    return obj.GetType().GetProperties().Select(n => n.Name);
            }

            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                    var prop = obj.GetType().GetProperty(binder.Name);
                    if (prop == null)
                    {
                            result = null;
                            return false;
                    }
                    else
                    {
                            result = prop.GetValue(obj, null);
                            return true;
                    }
            }

            public override int GetHashCode()
            {
                    return obj.GetHashCode();
            }

            public override string ToString()
            {
                    return obj.ToString();
            }

            public override bool Equals(object obj2)
            {
                    return obj.Equals(obj2);
            }                
 }
1 голос
/ 13 января 2019

мы можем сделать это с помощью Json

Контроллер: объект -> строка json, просмотр: строка Json -> объект

Scennerio - это просто класс контроллера, сериализующий объект C # в строку json затем представление получает эту строку и десериализует ее в объект, например:

в контроллере:

using Newtonsoft.Json;
ViewBag.Stuff = JsonConvert.SerializeObject(new { Name = "Test", Email = "user@domain.com" });

в представлении:

@using Newtonsoft.Json
<p>@JsonConvert.DeserializeObject(ViewBag.Stuff).Name</p>

Примечание: это было проверено в Asp.Net Core 2.2 , Проверьте эту ссылку, чтобы установить Newtonsoft.Json

0 голосов
/ 27 января 2017

Вы можете сделать это, используя механизм NothingsImpossible descibed, но без реализации собственной оболочки, используя ExpandoObject. Вот пример:

var items = _repository.GetItems()
    .Select(og => {
        dynamic eo = new System.Dynamic.ExpandoObject();
        eo.Id = item.Id;
        eo.FriendlyName = og.FriendlyName;
        eo.Selected = itemIds.Contains(item.Id);
        return eo;
    })
    .ToArray();
ViewBag.Items = items;
...