【问题标题】:renderpartial with null model gets passed the wrong type带有 null 模型的 renderpartial 传递了错误的类型
【发布时间】:2009-03-16 13:19:29
【问题描述】:

我有一个页面:

<%@ Page Inherits="System.Web.Mvc.View<DTOSearchResults>" %>

还有以下内容:

<% Html.RenderPartial("TaskList", Model.Tasks); %>

这里是 DTO 对象:

public class DTOSearchResults
{
    public string SearchTerm { get; set; }
    public IEnumerable<Task> Tasks { get; set; }

这里是部分:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Task>>" %>

当 Model.Tasks 不为空时,一切正常。但是,当它为空时,我得到:

传入字典的模型项是类型 'DTOSearchResults' 但此字典需要类型的模型项 'System.Collections.Generic.IEnumerable`1[Task]'。

我认为它一定不知道要使用哪个重载,所以我这样做(见下文)是为了明确,但我仍然遇到同样的问题!

<% Html.RenderPartial("TaskList", (object)Model.Tasks, null); %>

我知道我可以通过检查 null 或什至不传递 null 来解决此问题,但这不是重点。为什么会这样?

【问题讨论】:

    标签: asp.net-mvc renderpartial


    【解决方案1】:

    Andrew 我认为您遇到的问题是当您传递的模型为空时,RenderPartial 方法使用调用(视图)的模型到局部视图的结果。您可以通过执行以下操作来解决这种奇怪的行为:

    <% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary()); %>
    

    这有帮助吗?

    【讨论】:

    • 仍在节省人们的时间。我正在为此拉头发。
    • 我明白为什么他们支持空模型并传递页面模型但他们不能通过重载来处理它。 @Html.Render("donkeys") 不同于 @Html.Render("donkeys", couldbenull)
    • 我觉得这很违反直觉,所以我添加了一个“问题”,如果您同意,请投票:aspnet.codeplex.com/workitem/8872
    • 我发现使用这个解决方案,我的局部视图中的 ValidationSummary 不起作用,因为主模型的 ViewData 在局部视图中丢失了。我使用这里给出的答案stackoverflow.com/a/12037580/649497 来解决这个问题。
    • 你应该传递现有的 ViewData:new ViewDataDictionary(ViewData)
    【解决方案2】:

    @myandmycode 的答案很好,但会稍短一些

    <% Html.RenderPartial("TaskList", new ViewDataDictionary(Model.Tasks)); %>
    

    这是可行的,因为ViewDataDictionary 是保存模型的东西,它可以接受模型作为构造函数参数。这基本上传递了一个“整个”视图数据字典,当然它只包含可能为空的模型。

    【讨论】:

    • @jcmcbeth:呃,不,它没有......我已经成功地使用了这个带有空值的确切代码。
    • @jcmcbeth:你在用new ViewDataDictionary(null)吗?因为这会选择一个不同的重载,一个带有ViewDataDictionary 参数的重载,它可能不接受空值。
    • 使用 ViewBag 属性会导致调用错误的构造函数。它如何采用动态类型并假设它是对象上的 ViewDataDictionary 对我来说没有意义,但它似乎是它正在做的事情。您必须将其强制转换为对象才能选择正确的构造函数。
    • @jcmcbeth:通过动态类型调用它与您给出实际值一样;如果值为null,则与调用new ViewDataDictionary(null) 相同,这会导致调用最具体的重载。
    • 如果你这样使用它,字典错误就消失了。Html.RenderPartial("TaskList", new ViewDataDictionary(model: Model.Tasks))如果它为空,你使用了错误的构造函数。
    【解决方案3】:

    看起来,当您传入的模型的属性为空时,MVC 会故意恢复为“父”模型。显然,MVC 引擎将 null 模型值解释为使用前一个模型值的意图。

    这里有更多细节:ASP.NET MVC, strongly typed views, partial view parameters glitch

    【讨论】:

    • +1 表示实际上试图解释这个问题,而不仅仅是将其视为一种奇怪的行为
    • 是的,这发生在我身上,上面没有解决它,它只是给了我更多关于我的实际错误的信息。
    【解决方案4】:

    如果您不想在局部视图中丢失以前的 ViewData,您可以尝试:

    <% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary(ViewData){Model = null});%>
    

    【讨论】:

    • 这似乎无法回答问题。
    • +1 实际上它确实有效。它与stackoverflow.com/a/713921/649497 这里提出的想法基本相同,但解决了该答案的一个问题,即如果您使用空构造函数实例化 ViewDataDictionary,ViewData 将丢失。我首先用公认的解决方案解决了这个问题,然后发现我的 ValidationSummary 在局部视图中不起作用。这个解决方案为我解决了这个问题。这个答案需要更多的认可才能解决问题并在您的局部视图中保留 ViewData。
    • @Franc P 这实际上在没有丢失 ViewBag 值的情况下工作,因此传递了一个空模型。谢谢。
    • 如果您需要在 Partials 中访问 ViewBag,这是正确的答案!
    【解决方案5】:

    一种解决方案是像这样创建一个 HtmlHelper:

    public static MvcHtmlString Partial<T>(this HtmlHelper htmlHelper, string partialViewName, T model)
    {
        ViewDataDictionary viewData = new ViewDataDictionary(htmlHelper.ViewData)
        {
            Model = model
        };
        return PartialExtensions.Partial(htmlHelper, partialViewName, model, viewData);
    }
    

    Partial&lt;T&gt;(...)Partial(...)之前匹配,非常方便,编译时不会出现歧义错误。

    我个人觉得很难理解这种行为 - 似乎很难将其想象为设计选择?

    【讨论】:

    • 这就是我最后所做的。在 asp.net mvc 中没有多少设计选择/行为是有意义的。既然放弃了。对其他人有帮助,所以有一个 +1
    • 不错,但用户不清楚。假设我已经习惯了我的同事在他的项目中使用的东西,我开始了一个新的。然后完全忘记添加这个重载和voilla,异常开始在生产中发生,因为我们没有对它进行足够好的测试。一个不同的名字是更好的恕我直言。
    • 使用此扩展方法,某些工具将无法超链接到视图。
    【解决方案6】:

    虽然已经回答了这个问题,但我遇到了这个问题,并决定为我的项目解决这个问题,而不是使用 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&lt;object&gt; 模型的方法和丢弃的方法也可以使用 Razor lambda 调用,允许您使用一些 html 包装部分结果。

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

    【讨论】:

    • 自 MVC5 起仍然有用:2014 年 6 月 25 日。谢谢。
    【解决方案7】:

    我的解决方法是:

    <% Html.RenderPartial("TaskList", Model.Tasks ?? new List()); %>

    【讨论】:

    • 这是一个肮脏的解决方案。在您的局部视图中,您应该能够检查 null 模型,而不是检查 list 是否有任何值以及它是否为 null。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    相关资源
    最近更新 更多