MVC Razor动态模型,“对象”不包含“ PropertyName”的定义


106

将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 =”行上看到一条错误消息:

“对象”不包含“产品”的定义

谁能向我解释为什么我会收到该错误?同样,当我在调试模式下观看Model对象时,它看起来还不错(具有2个属性:Products和Threshold)


Answers:


150

您是否将匿名类的实例作为视图模型传递?我只是尝试了这一点(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)通过以下澄清编辑了他的帖子:

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


1
编辑很高兴知道。我只是遇到了同样的问题,并且不了解那里的WTF。感谢您的解释。
Yanick Rochon

18
编辑#2建议现在(MVC> 3)可以做行以标记“错误”?return View(new { Foo = 1, Bar = "test" });?因为我使用的是MVC 4,并且仍然收到“对象不包含Foo的定义”的信息
运动

@也给我运动...您找到了解决方法吗?(旁边的ToExpando
Alex

2
所以现在在2018年使用ASP.NET Core 2.1和Razor视图,我发现原始问题中的错误仍然困扰着我。因此,我不知道有关修复MVC 3的内容是怎么回事,因为它似乎仍然很糟糕。
Andrew Arnott

41

在.NET 4.0上,可以轻松将匿名类型转换为ExpandoObjects,因此所有问题都可以通过转换本身的开销解决。在这里查看


别客气。也许这会触发M $以使匿名类型更可用
Adaptabi

不过,这是否适用于局部变量?我收到一个错误消息,无法动态调度
Partials

1
什么偏?你能举个例子吗?
Adaptabi 2012年

27

这与具有内部属性的匿名类型无关

它是完全有可能从一个视图传递匿名类型的局部视图

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

因此,对于OP的问题,@ Lucas的答案无关紧要-即使解决方法可行

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

那么,是什么导致突然的失败,将匿名类型从视图传递给局部视图呢?

至少在我的情况下,我发现这是由于在SAME FOLDER中具有另一个视图,该视图指定了无法解析的模型类型。视图在运行时进行编译,因此在运行时编译视图失败也将意味着编译动态类型失败,而部分视图将仅接收object。目前尚不清楚发生了什么,但是在OP的特定示例(和我的示例)中,这很可能是造成问题的原因。

有趣的是,如果模型类型正确,但是视图的另一部分未编译,则匿名类型不会以相同的方式受到影响。这必须取决于Razor如何分解视图组成部分的动态编译。

纠正了有问题的视图后,请重新构建整个解决方案或清理并重新构建项目,然后再检查其是否已修复。

为了确保您不会再次被此困扰,您可以通过将Razor视图添加到csproj文件中来启用编译时编译:

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

2
这解决了我的问题-最初使用“ @model dynamic”似乎是正确的解决方法,但实际上却使我误入歧途。
crimbo 2014年

我清理了解决方案,然后重新构建它,错误消失了。
maxbeaudoin

我已经更新了我的答案,因为MVC 3,以反映MVC的动态视图模型的支持
卢卡斯

对于庞大的代码库,不时启用视图编译总是很有用的。揭示了各种各样的问题,错别字,与T4MVC得益于强劲的打字错误,它推出等等
丹尼斯的威胁

哦,对:我刚刚注意到我们在这里谈论从视图传递到局部视图。不是从控制器到视图,这是我的问题。
mwardm '16

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());

1
似乎是unnecssary开销我首先创建一个动态的对象,然后创建一个ExpandoObject ...只是创建ExpandoObject而不是..
Baz1nga

@ Baz1nga您不能执行... new Expando(){prop = value,...},这使其成为问题。我正在使用Json.Net的JObject进行类似的用法。
Tracker1 2012年

3
在其中拥有HtmlHelper感觉是错误的。公共静态ExpandoObject ToExpando(此对象o){IDictionary <string,object> expando = new ExpandoObject(); foreach(o.GetType()。GetProperties()中的var propertyInfo)} return(ExpandoObject)expando; }
erlando 2012年

6

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

您可以使用@ViewData.Eval("foo")代替调用匿名对象属性@Model.foo

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

我最近在Facebook Social Comments Integration的视图之间传递一些属性时遇到了这个问题。示例代码:

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>

0

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


0

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

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

-6

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.