C# 在ViewBag中存储匿名对象
这可能是一个愚蠢的问题,但我试图在C# 在ViewBag中存储匿名对象,c#,asp.net-mvc-3,reflection,anonymous-types,viewbag,C#,Asp.net Mvc 3,Reflection,Anonymous Types,Viewbag,这可能是一个愚蠢的问题,但我试图在ViewBag中填充一个匿名对象,如下所示: ViewBag.Stuff = new { Name = "Test", Email = "user@domain.com" }; 并从如下视图访问它: @ViewBag.Stuff.Name 我知道ViewBag是动态的,“Stuff”是一个匿名对象。。。但是当我从上面的视图行查看调试器时,我可以看到所有具有正确值的属性。为什么模型绑定器在这方面会遇到如此困难 有没有一种不用创建模型类就可以实现这一点的好方法?我
ViewBag
中填充一个匿名对象,如下所示:
ViewBag.Stuff = new { Name = "Test", Email = "user@domain.com" };
并从如下视图访问它:
@ViewBag.Stuff.Name
我知道ViewBag是动态的,“Stuff”是一个匿名对象。。。但是当我从上面的视图行查看调试器时,我可以看到所有具有正确值的属性。为什么模型绑定器在这方面会遇到如此困难
有没有一种不用创建模型类就可以实现这一点的好方法?我想继续使用
new{}
本质上,问题是匿名类型生成为internal(),使得无法从视图中对对象属性进行硬类型引用。本文提供了更详细的解释:
使用动态匿名包装类(@Dakill's answer)是可以实现的,但很快就会变得难看,这会让程序员问他/她为什么会这样做。与流行的观点相反,这是可以做到的,但涉及到一种有点难看的黑客行为,这将导致以后的维护问题。。它包括编写一个类,将匿名对象“包装”为动态对象。不久前我把它作为一个练习,下面是包装器类的代码,您可以像
ViewBag.Stuff=newdynamicanonymous(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);
}
}
public类dynamicanyMous:DynamicObject
{
对象对象对象;
公共动态(对象o)
{
这是obj=o;
}
公共重写IEnumerable GetDynamicMemberNames()
{
返回obj.GetType().GetProperties().Select(n=>n.Name);
}
公共重写bool TryGetMember(GetMemberBinder绑定器,输出对象结果)
{
var prop=obj.GetType().GetProperty(binder.Name);
if(prop==null)
{
结果=空;
返回false;
}
其他的
{
结果=prop.GetValue(obj,null);
返回true;
}
}
公共覆盖int GetHashCode()
{
返回obj.GetHashCode();
}
公共重写字符串ToString()
{
返回obj.ToString();
}
公共覆盖布尔等于(对象obj2)
{
返回obj.Equals(obj2);
}
}
您可以使用前面描述的机制来完成,但不需要使用ExpandooObject实现您自己的包装器。以下是一个例子:
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;
我们可以使用Json实现这一点
控制器:对象->json字符串,视图:json字符串->对象
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>
使用Newtonsoft.Json
@JsonConvert.DeserializeObject(ViewBag.Stuff).Name
注意:这是在Asp.NETCore2.2中测试的
,检查安装链接您可以使用@ViewBag.Stuff.Name或@ViewBag.Stuff.Email吗??原因测试是一个值,而不是一个键/属性,它是一个输入错误,已经修复。我一直在尝试访问属性,而不是它们的值。谢谢。事实证明,这是不可能做到的。看到这个:。@SoWeLie谢谢你把它挖出来。我只是编辑了它,让下一个人更容易找到。。。用这个链接编辑你的答案,并总结关于“内部”的内容,我会将你标记为答案。我正在寻找一个关于是否可以这样做的答案,如果不能,为什么。。。(顺便说一句,我没有投你反对票)那么,我再给你一个答案。然而,我仍然坚持这个答案,如果您试图构建一个可维护的应用程序,您应该做什么。