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

Ruu*_*ier 104 razor asp.net-mvc-3

使用MVC 3和Razor视图引擎.我有这个观点:

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

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

@Html.Partial("PartialViewName", new { Products = Model, Threshold = 5 })
Run Code Online (Sandbox Code Playgroud)

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

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

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

Luc*_*cas 149

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

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

// worked
return View(new TestClass { Foo = 1, Bar = "test" });
Run Code Online (Sandbox Code Playgroud)

编辑#1:

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

编辑#2:

David Ebbo根据这一澄清编辑了他的帖子:

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

  • 编辑#2表明现在(MVC> 3)可以做行标记为"错误"?`return View(new {Foo = 1,Bar ="test"});`?因为我正在使用MVC 4并仍然得到"对象不包含Foo的定义" (17认同)
  • 所以现在在 2018 年使用 ASP.NET Core 2.1 和 Razor 视图,我发现原始问题中的错误仍然困扰着我。所以我不知道这个关于 MVC 3 修复这个问题的讨论是关于什么的,因为它似乎仍然坏了。 (2认同)

Ada*_*abi 40

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


jos*_*ley 25

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

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

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

因此,就OPs问题而言,@ Lucas的答案是无关紧要的 - 即使解决方法可行.

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

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

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

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

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

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

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

  • 这解决了我的问题 - 使用“@model dynamic”最初似乎是正确的解决方法,但实际上却让我走上了错误的道路。 (2认同)

小智 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;
            }

        }
    }
Run Code Online (Sandbox Code Playgroud)

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

    return View(new {x=4, y=6}.ToExpando());
Run Code Online (Sandbox Code Playgroud)

  • 在那里使用HtmlHelper感觉不对... public static ExpandoObject ToExpando(this object o){IDictionary <string,object> expando = new ExpandoObject(); foreach(o.GetType()中的var propertyInfo.GetProperties()){expando.Add(new KeyValuePair <string,object>(propertyInfo.Name,propertyInfo.GetValue(o,index:null))); } return(ExpandoObject)expando; } (3认同)

Jam*_*esG 8

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

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

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

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

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

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

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