【问题标题】:ASP.NET MVC, strongly typed views, partial view parameters glitchASP.NET MVC,强类型视图,部分视图参数故障
【发布时间】:2010-11-06 03:34:06
【问题描述】:

如果我得到继承自的视图:

System.Web.Mvc.ViewPage<Foo>

Foo 的属性 Bar 的类型为 string
并且视图想要渲染强类型的局部视图,它继承自:

System.Web.Mvc.ViewUserControl<string>  

像这样:

Html.RenderPartial("_Bar", Model.Bar);%>

那为什么会抛出这个:

传入字典的模型项的类型为“Foo”
但是这个字典需要一个“System.String”类型的模型项。

什么时候bar没有初始化?

更具体:为什么它传递 Foo,它应该在哪里传递 null?

【问题讨论】:

  • 生成局部视图的代码是什么?
  • 我有同样的问题,但我自己的类型,而不是 System.String,所以没有“默认”可以代替。也许我应该把它变成一个非强类型的局部视图,并检查传递的类型?
  • @Dave,我没有问题——我知道它是这样工作的。在您的情况下 - 只需在渲染任何内容之前检查 null (创建 RenderPartialIfNotNull htmlhelper 方法可能很方便)。

标签: asp.net-mvc null strongly-typed-view


【解决方案1】:

如果您将 null 作为模型传递给 RenderPartial,那么它将查看原始模型,这就是错误显示 foo 的原因。

您需要确保将 bar 初始化为空字符串而不是 null。

编辑: @Arnis,看看源代码。它不会说谎。 您将 null 传递给 RenderPartial 的重载。 您没有传递 Foo。在内部,当您将空 Bar 传递给 RenderPartial 时,系统会使用您页面的 ViewContext(即 Foo)中的模型。

【讨论】:

  • 这个答案对我来说似乎是错误的。问题是:“为什么它通过 Foo,它应该在哪里通过 null?”而不是“它是否通过 Foo 而不是 null?”。
  • @Dennis 确定它没有说谎,但它没有回答为什么需要它的问题。 tvanfosson 说出了原因。不管怎么说,还是要谢谢你。 :)
【解决方案2】:

查看 ASP.NET MVC 源代码(HtmlHelper.cs -> RenderPartialInternal 方法 -> 第 258 行):

...

if (model == null) {
    if (viewData == null) {
        newViewData = new ViewDataDictionary(ViewData);
    }

...

这正是你的情况。 ASP.NET MVC 使用 ViewContext 中的 ViewData

更新:

试试这个:

<% Html.RenderPartial("_Bar", Model.Bar ?? "Default" ); %>

【讨论】:

【解决方案3】:

正如@Dennis 指出的那样,如果模型值为空,它将使用视图中的现有模型。这样做的原因是支持使用仅包含局部视图名称的签名调用局部视图并使其重用现有模型的能力。在内部,所有 RenderPartial 助手都遵循一个 RenderPartialInternal 方法。让该方法重用现有模型的方法是为模型传入一个空值(仅采用视图名称的签名就是这样做的)。当您将空值传递给同时包含视图名称和模型对象的签名时,您实际上是在复制仅采用视图名称的方法的行为。

这应该可以解决您的问题:

<% Html.RenderPartial( "_Bar", Model.Bar ?? string.Empty ) %>

【讨论】:

  • 之所以起作用,是因为 Foo 的类型为 string。显然,这就是问题所要问的。 =) 但是为了将来参考(我是如何找到这个页面的),如果 Foo 是一个复杂类型(在我的例子中),你基本上将整个 Html.RenderPartial 调用包装在一个检查中以查看 Foo 是否为非空。仅供参考!
  • @kdawg -- 或者只使用空合并运算符和第二个操作数为模型类型的合适默认值,例如,new Foo()
  • 这确实适用于字符串,但是当您使用其他复杂类型时,您需要指定一个新的 ViewDataDictionary() { Model = Model.Bar } 作为 RenderPartial 的第三个参数。
  • ...如果您还需要保留模型以外的字典内容,这将不起作用。我认为这种情况没有明显的解决方案。还有其他人吗?
  • @KjellRilbe 如果需要添加其他属性,我会多次为视图创建单独的 ViewDataDictionary。编写一个从当前 ViewData 传播到这样一个字典的帮助器不需要太多努力,然后您可以向其中添加其他项目和/或修改模型。
【解决方案4】:

虽然已经回答了这个问题,但我遇到了这个问题,并决定为我的项目解决这个问题,而不是使用“new ViewDataDictionary()”来解决它。

我创建了一组扩展方法: https://github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs
我还添加了一些模型为null时不调用partial的方法,这样会节省很多if语句。

我为 Razor 创建了它们,但其中一些也应该适用于 aspx 样式视图(使用 HelperResult 的视图可能不兼容)。

扩展方法如下所示:

@* calls the partial with Model = null *@
@Html.PartialOrNull("PartialName", null)
@* does not call the partial if the model is null *@
@Html.PartialOrDiscard("PartialName", null)

还有一些用于 IEnumerable 模型的方法,丢弃的模型也可以使用 Razor lambda 调用,允许您使用一些 html 包装部分结果。

如果您愿意,请随意使用它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多