Сохранение анонимного объекта в ViewBag
Это, наверное, глупый вопрос, но я пытаюсь записать анонимный объект в ViewBag
так:
ViewBag.Stuff = new { Name = "Test", Email = "[email protected]" };
и получить доступ к нему из представления так:
@ViewBag.Stuff.Name
Я понимаю, что ViewBag является динамическим и что "Stuff" является анонимным объектом... но когда я смотрю с отладчиком из строки "Вид" выше, я могу видеть все свойства с соответствующими значениями. Почему такое связующее устройство моделирует с этим трудное время?
Есть ли хороший способ сделать это без создания класса модели? Я хочу продолжить использование new {}
Ответы
Ответ 1
По существу, проблема заключается в том, что анонимные типы генерируются как внутренние (см. ответ), что делает жесткие типизированные ссылки на свойство объекта невозможным из представления. В этой статье приводится более подробное объяснение:
http://www.heartysoft.com/anonymous-types-c-sharp-4-dynamic
Можно выполнить с использованием класса-оболочки динамического анонимного (ответ @Dakill), но он становится уродливым и должен задать вопрос программисту, почему он/она будет делать это.
Ответ 2
Вопреки распространенному мнению, это может быть сделано, но включает в себя несколько уродливый взломать, что приведет к проблемам обслуживания в будущем. Это включает в себя запись класса, чтобы "обернуть" ваш анонимный объект в динамический объект. Я сделал это как упражнение некоторое время назад, ниже - код класса оболочки, вы использовали бы его как ViewBag.Stuff = new DynamicAnonymous(new { Name = "Test", Email = "[email protected]" });
..
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);
}
}
Ответ 3
Вы можете сделать это, используя механизм 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;
Ответ 4
мы можем сделать это с помощью Json
Контроллер: объект → строка json, Вид: строка Json → объект
Scenerio - это просто класс контроллера, сериализующий объект С# в строку json, затем представление получает эту строку и десериализует ее в объект, например:
в контроллере:
using Newtonsoft.Json;
ViewBag.Stuff = JsonConvert.SerializeObject(new { Name = "Test", Email = "[email protected]" });
ввиду:
@using Newtonsoft.Json
<p>@JsonConvert.DeserializeObject(ViewBag.Stuff).Name</p>
Примечание: это было проверено в Asp.Net Core 2.2, проверьте эту ссылку, чтобы установить Newtonsoft.Json