MVC Razor动态模型,'object'不包含'PropertyName'的定义

时间:2011-02-01 11:47:24

标签: asp.net-mvc-3 razor

将MVC 3与Razor视图引擎一起使用。 我有这个观点:

@model dynamic
@{
    var products = (List<ListItemBaseModel>)Model.Products;
    var threshold = (int)(Model.Threshold ?? 1);
    var id = Guid.NewGuid().ToString();
}

使用此代码从另一个视图调用它:

@Html.Partial("PartialViewName", new { Products = Model, Threshold = 5 })

在两个视图中,当我调试它们并观看模型时,它似乎包含正确的对象。 当我执行代码时,我在“var products =”行上收到错误说:

'object'不包含'Products'的定义

任何人都可以向我解释为什么我会收到这个错误? 同样,当我在调试模式下观察Model对象时,它看起来很好(具有2个属性:Products和Threshold)

8 个答案:

答案 0 :(得分:149)

您是否将匿名类的实例作为视图模型传递?我刚试过这个(CSHTML中的动态视图模型),并且在使用匿名类时遇到了同样的错误,但如果我创建了一个命名类,它就可以正常工作。我搜索了但没有在任何地方看到这个记录。

// error
return View(new { Foo = 1, Bar = "test" });

// worked
return View(new TestClass { Foo = 1, Bar = "test" });

编辑#1:

根据David Ebbo,您无法将匿名类型传递到动态类型视图,因为匿名类型编译为internal。由于CSHTML视图被编译为单独的程序集,因此无法访问匿名类型的属性。

编辑#2:

David Ebbo编辑了他的帖子:

  

Note(12/22/2011):现在MVC 3直接支持动态,不再需要以下技术。这篇文章实际上是导致将该功能集成到MVC中的原因!

答案 1 :(得分:40)

在.NET 4.0上,匿名类型可以很容易地转换为ExpandoObjects,因此所有问题都可以通过转换本身的开销来解决。 查看here

答案 2 :(得分:25)

这与具有内部属性

的匿名类型无关

完全可能将匿名类型从视图传递到局部视图

我今天遇到了同样的问题,并没有(直接)处理传递匿名类型及其固有internal属性的问题。

因此,就OP问题而言,@ Lucas的答案是无关紧要的 - 即使解决方法将起作用

在OPs问题中,匿名类型正在从程序集X中的视图 传递到程序集X中的部分 ,因此David Ebbo概述了匿名类型的内部属性是无关紧要的; 为视图编译的类型,部分和匿名类型都包含在同一个程序集中

那么是什么导致突然失败将匿名类型从视图传递到部分?

至少在我的情况下,我发现这是因为在相同文件夹中有另一个视图指定了无法解析的模型类型。视图在运行时被编译,因此在运行时编译视图时失败也意味着编译动态类型失败,而部分只会收到object。现在并不是很明显,但在OPs的具体例子(和我的)中,这很可能是导致问题的原因。

值得注意的是,如果模型类型正确但视图的另一部分未编译,则匿名类型不会以相同方式受到影响。这必须归结为Razor如何分解视图组成部分的动态编译。

纠正违规视图后,重建整个解决方案或清理并重建项目,然后再检查项目是否已修复。

为了确保您不会再被这一点抓住,您可以通过将Razor视图添加到csproj文件来启用编译时编译:

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>

答案 3 :(得分:9)

在解决方案的任何位置添加以下类(使用System命名空间,因此无需添加任何引用即可使用) -

    namespace System
    {
        public static class ExpandoHelper
        {
            public static ExpandoObject ToExpando(this object anonymousObject)
            {
                IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
                IDictionary<string, object> expando = new ExpandoObject();
                foreach (var item in anonymousDictionary)
                    expando.Add(item);
                return (ExpandoObject)expando;
            }

        }
    }

将模型发送到视图时,将其转换为Expando:

    return View(new {x=4, y=6}.ToExpando());

答案 4 :(得分:3)

而不是在局部视图中使用dynamic模型类型。

您可以使用@ViewData.Eval("foo")而不是@Model.foo来调用匿名对象属性。

然后您可以从视图中删除@Model dynamic

最近我在Facebook社交评论集成的视图之间传递了一些属性时遇到了这个问题。示例代码:

Html.RenderPartial(@"Layouts/Partials/_Comments", new {currentUrl = Model.CurrentPage.GetAbsoluteUrl(), commentCount = 5 });

然后在我看来,我只有这个div:

<div class="fb-comments" data-href="@ViewData.Eval("currentUrl")" data-numposts="@ViewData.Eval("commentCount")" data-width="100%"></div>

答案 5 :(得分:0)

我不确定您是否收到此错误,因为您没有实施解决方法。我在局部视图中得到了同样的错误。解决方案只是清理构建并重建它。如果语法正确,代码应该可以工作,但剃刀引擎可能无法正确更新代码更改。

答案 6 :(得分:0)

我通过使用字典解决了这个问题。

 @Html.Partial("_Partial", new Dictionary<string, string> { { "Key1", "Val1" }, { "Key2", "Val2" }, { "Key3", "Val3" } });

答案 7 :(得分:-6)

要使用dynamic类型,您需要引用Microsoft.CSharp程序集