在ViewBag中存储匿名对象
本文关键字:对象 存储 ViewBag | 更新日期: 2023-09-27 18:21:07
这可能是一个愚蠢的问题,但我正试图在ViewBag
中填充一个匿名对象,如下所示:
ViewBag.Stuff = new { Name = "Test", Email = "user@domain.com" };
并从这样的视图访问它:
@ViewBag.Stuff.Name
我知道ViewBag是动态的,"Stuff"是一个匿名对象。。。但是当我从上面的View行查看调试器时,我可以看到所有具有正确值的属性。为什么模型活页夹在这方面遇到如此困难?
有没有一种好的方法可以在不创建模型类的情况下实现这一点?我想继续使用new {}
本质上,问题是匿名类型是作为内部生成的(请参阅答案),这使得视图中无法对对象属性进行硬类型引用。本文提供了一个更详细的解释:
http://www.heartysoft.com/anonymous-types-c-sharp-4-dynamic
使用动态匿名包装类(@Dakill的答案)是可以实现的,但速度很快就会变得很糟糕,应该会让程序员质疑他/她为什么要这样做。
与流行的观点相反,这是可以做到的,但涉及到一个有点丑陋的破解,这将导致未来的维护问题。。它包括编写一个类,将匿名对象"包装"为动态对象。我不久前就把它作为一个练习,下面是包装器类的代码,您可以像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);
}
}
使用Json 我们可以很好地实现这一点
控制器:对象->json字符串,视图:json字符串->object
scenerio只是控制器类将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
您可以使用NothingsImpossible描述的机制来实现这一点,但无需使用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;