在MVC5 Razor视图中传递动态模型

8

我正在尝试从控制器将动态结果传递到视图,方法 ShowColor 返回动态结果。在视图中,我尝试循环遍历集合,但是出现了错误。

'object' 不包含 'ColorID' 的定义。

我在控制器和视图中有以下代码:

public class myColor
{
    public int ID { get; set; }
    public string  Name { get; set; }
    public string Like { get; set; }
}

public dynamic ShowColor()
{
    IList<myColor> color = new List<myColor>();
    color.Add(new myColor { ID = 1, Name = "Red", Like = "***" });
    color.Add(new myColor { ID = 2, Name = "Green", Like = "*****" });
    color.Add(new myColor { ID = 3, Name = "Blue", Like = "**" });
    color.Add(new myColor { ID = 4, Name = "Yellow", Like = "*" });

    var select = (from c in color
                  select new
                  {                     
                      ColorID = c.ID,
                      ColorName = c.Name
                  }).ToList();

    return select;
}
public ActionResult DBDynamic()
{
    return View(ShowColor());
}

查看

@model dynamic

@{
    ViewBag.Title = "DBDynamic";
}

<h2>DBDynamic</h2>

<p>
    <ul>
        @foreach (var m in Model)
        {
            <li> @m.ColorID</li>            
        }
    </ul>

</p>

错误

调试图像

找到了解决方案这里有一个好的博客这里:

public static ExpandoObject ToExpando(this object anonymousObject)
{
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(anonymousObject))
    {
        var obj = propertyDescriptor.GetValue(anonymousObject);
        expando.Add(propertyDescriptor.Name, obj);
    }

    return (ExpandoObject)expando;
}

并且像这样调用它

    var select = (from c in color
                select new
                {
                    ColorID = c.ID,
                    ColorName = c.Name
                })
                .AsEnumerable()
                .Select(x => x.ToExpando());

return View(select);

在你的 Razor 视图中设置一个断点,看看你的结果是什么。 - jamesSampica
我在文章底部添加了一张调试图片。 - sairfan
你解决了这个问题吗?我刚遇到了类似的问题,看看你有没有什么想法。 - Haobo
我终于解决了我的问题,但我们场景之间的区别是你在一些Linq表达式中使用匿名类,而我正在使用JSON对象。 - Haobo
是的,我也得出了同样的解决方案,我认为最好的方法是避免在模型中使用动态类型,而是使用ViewModel,但在某些情况下,JSON结果可能很有用。 - sairfan
@Haobo,我在问题的末尾发布了一种解决方案。 - sairfan
1个回答

6

匿名对象和dynamic不是同一物。如果想像使用dynamic一样使用它,请将其转换为:

@foreach (dynamic m in Model)

然而,最好尽可能避免使用动态类型。你会失去所有的编译时检查,甚至智能提示。你可能不知道直到运行时才意识到属性名称输入错误或者错误地以错误方式使用了某种类型。如果出现问题,您希望在编译时就知道,而不是当它已经上线并影响用户时才发现,除非用户通知您,否则您甚至可能不知道出现了错误。这对于您的应用程序来说是一个可怕的情况。

总之,使用强类型。如果你想要一个带有属性的东西,比如ColorIDColorName,请创建一个包含这些属性的视图模型,并将查询选择为该类型的实例。然后,一切都会很好地强制类型,您会提前知道代码中是否存在某些错误或问题。


得到相同的错误信息。 - sairfan
也许问题在于你的模型本身是动态的。将其更改为 List<object>IEnumerable<object>,看看会发生什么。 - Chris Pratt
IEnumerable<object>,List<object> 不起作用,报告相同的错误。 - sairfan
“dynamics are best avoided”不是真的。当您使用动态语言时,希望在运行时使用变量,因此不需要编译时检查。您希望能够即时创建对象。如果要多次使用,则创建强类型。最好说,使用动态语言可以模仿JavaScript的行为,有时这是有益的。 - Herman Van Der Blom
@HermanVanDerBlom:动态确实更容易,但像生活中的大多数事情一样,这种便利是有代价的。在这里,您正在引入应用程序中错误的潜在向量。如果您正在执行类似于ViewBag.Title =“Foo”的操作,则极不可能出错,因此您可能没问题。但是,您越复杂,出现故障的机会就越大。运行时错误是成功应用程序的祸根。 - Chris Pratt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接