带有null模型的renderpartial传递错误的类型

And*_*ock 193 asp.net-mvc renderpartial

我有一个页面:

<%@ Page Inherits="System.Web.Mvc.View<DTOSearchResults>" %>
Run Code Online (Sandbox Code Playgroud)

在其上,以下内容:

<% Html.RenderPartial("TaskList", Model.Tasks); %>
Run Code Online (Sandbox Code Playgroud)

这是DTO对象:

public class DTOSearchResults
{
    public string SearchTerm { get; set; }
    public IEnumerable<Task> Tasks { get; set; }
Run Code Online (Sandbox Code Playgroud)

这是部分:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Task>>" %>
Run Code Online (Sandbox Code Playgroud)

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

传递到字典中的模型项的类型为'DTOSearchResults',但此字典需要类型为'System.Collections.Generic.IEnumerable`1 [Task]'的模型项.

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

<% Html.RenderPartial("TaskList", (object)Model.Tasks, null); %>
Run Code Online (Sandbox Code Playgroud)

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

mea*_*ode 341

安德鲁我认为你得到的问题是RenderPartial方法的结果,当你传递的模型为null时,使用调用(视图)的模型到局部视图.你可以通过这样做来解决这个奇怪的行为:

<% Html.RenderPartial("TaskList", Model.Tasks, new ViewDataDictionary()); %>
Run Code Online (Sandbox Code Playgroud)

这有帮助吗?

  • 我发现这非常违反直觉所以我添加了一个"问题",如果你同意就投票给它:http://aspnet.codeplex.com/workitem/8872 (17认同)
  • 仍在节省人们的时间.我把头发拉过来. (14认同)
  • 你应该传递现有的ViewData:new ViewDataDictionary(ViewData) (5认同)
  • 我明白为什么他们支持null模型并传递页面Model但是他们不能通过重载来处理它.@ Html.Render("donkeys")与@ Html.Render("donkeys",canbenull)不同 (3认同)
  • 我发现使用这个解决方案,我的部分视图中的ValidationSummary不起作用,因为主模型的ViewData在局部视图中丢失了.我使用http://stackoverflow.com/a/12037580/649497给出的答案来解决这个问题. (3认同)

con*_*tor 46

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

<% Html.RenderPartial("TaskList", new ViewDataDictionary(Model.Tasks)); %>
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为它ViewDataDictionary是持有模型的东西,它可以接受模型作为构造函数参数.这基本上传递了一个"整个"视图数据字典,当然它只包含可能为空的模型.

  • @jcmcbeth:呃,不,它没有......我已经成功地使用了这个带有空值的确切代码。 (2认同)
  • 如果你像这样使用它,字典错误就会消失。`Html.RenderPartial("TaskList", new ViewDataDictionary(model: Model.Tasks))` 如果构造函数为空,则您使用了错误的构造函数。 (2认同)

小智 24

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

这里稍微详细一点:ASP.NET MVC,强类型视图,局部视图参数故障


Fra*_*n P 20

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

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

  • +1实际上它确实有效.它基本上与http://stackoverflow.com/a/713921/649497中提出的相同,但克服了该答案的问题,即如果使用空构造函数实例化ViewDataDictionary,ViewData将会丢失.我首先用接受的解决方案解决了这个问题,然后发现我的ValidationSummary在部分视图中不起作用.这个解决方案为我解决了.这个答案需要更多的识别来解决问题并在局部视图中保留ViewData. (6认同)

Col*_*ame 12

一个解决方案是创建一个像这样的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);
}
Run Code Online (Sandbox Code Playgroud)

Partial<T>(...)之前的匹配Partial(...),从而方便编译时没有歧义错误.

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


Jaa*_*aap 11

虽然这已经得到了解答,但我遇到了这个并决定我想为我的项目解决这个问题,而不是解决它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)
Run Code Online (Sandbox Code Playgroud)

还有IEnumerable<object>模型的方法,丢弃的方法也可以用Razor lambda调用,允许你用一些html包装部分结果.

如果你愿意,可以随意使用它们.