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谢谢你把它挖出来。我只是编辑了它,让下一个人更容易找到。。。用这个链接编辑你的答案,并总结关于“内部”的内容,我会将你标记为答案。我正在寻找一个关于是否可以这样做的答案,如果不能,为什么。。。(顺便说一句,我没有投你反对票)那么,我再给你一个答案。然而,我仍然坚持这个答案,如果您试图构建一个可维护的应用程序,您应该做什么。