ChatGPT解决这个技术问题 Extra ChatGPT

MVC Razor 动态模型,“对象”不包含“属性名称”的定义

使用带有 Razor 视图引擎的 MVC 3。我有这个观点:

@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 =”行出现错误:

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

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


L
Lucas

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

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


很高兴知道编辑。我只是遇到了同样的问题并且不了解那里的WTF。感谢您的解释。
编辑#2建议现在(MVC&gt; 3)可以将行标记为“错误”? return View(new { Foo = 1, Bar = "test" }); ?因为我正在使用 MVC 4 并且仍然得到“对象不包含 Foo 的定义”
@sports me too...你找到解决方法了吗? (在 ToExpando 旁边)
所以现在在 2018 年使用 ASP.NET Core 2.1 和 Razor 视图,我发现原来问题中的错误仍然在咬我。所以我不知道关于 MVC 3 修复这个问题的全部内容是什么,因为它看起来仍然很糟糕。
C
Community

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


不客气。也许这会踢 M$ 使匿名类型更可用
这是否适用于部分?我收到一个错误,无法动态分派 Partials...
什么部分?你能举个例子吗?
j
joshcomley

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

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

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

因此,关于 OPs 问题,@Lucas 的答案是无关紧要的——即使解决方法可行。

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

那么是什么导致突然无法将匿名类型从视图传递到局部?

至少在 我的 情况下,我发现这是由于 SAME FOLDER 中的另一个视图指定了无法解析的模型类型。视图是在运行时编译的,因此在运行时编译视图失败也意味着编译动态类型失败并且部分将简单地接收 object 是有意义的。发生了什么并不是很明显,但在 OPs 的特定示例(和我的)中,这很可能是问题的原因。

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

纠正有问题的视图后,要么重建整个解决方案,要么清理并重建项目,然后再检查它是否已修复。

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

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

这解决了我的问题 - 最初使用“@model dynamic”似乎是正确的解决方法,但实际上让我走错了路。
我清理了解决方案,重建了它,错误消失了.. 121 票错了。
我已经更新了我的答案,以反映自 MVC 3 以来 MVC 对动态视图模型的支持。
不时启用视图编译对于庞大的代码库总是有用的。由于引入了强类型等,揭示了 T4MVC 的各种问题、拼写错误、错误等。
哦,对了:我刚刚注意到我们在这里讨论的是从视图传递到局部视图。不是从控制器到视图,这是我的问题。
S
Segev -CJ- Shmueli

在您的解决方案中的任何位置添加以下类(使用 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());

对我来说,首先创建一个动态对象然后创建一个 ExpandoObject 似乎是不必要的开销......只需创建 ExpandoObject ......
@Baz1nga 你不能这样做... new Expando() { prop=value, ... },这使它有问题。我将 Json.Net 的 JObject 用于类似用途。
在那里有 HtmlHelper 感觉不对... public static ExpandoObject ToExpando(this object o) { IDictionary expando = new ExpandoObject(); foreach ( var propertyInfo in o.GetType().GetProperties() ) { expando.Add(new KeyValuePair(propertyInfo.Name, propertyInfo.GetValue(o, index: null))); } return (ExpandoObject) expando; }
J
JamesG

而不是在局部视图中使用 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>

g
goran

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


G
Gerade Geldenhuys

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

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

t
the_joric

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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅