带有空模型的Renderpartial传递了错误的类型

我有一页:

<%@ 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>>" %>

当模型。Tasks不是空的,一切正常。然而,当它为空时,我得到:

传递给字典的模型项是类型的 'DTOSearchResults'但是这个字典需要一个类型的模型项 1[任务]' System.Collections.Generic.IEnumerable。< / p >

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

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

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

49828 次浏览

Andrew我认为你得到的问题是RenderPartial方法使用调用(视图)的模型到局部视图的结果,当你传递的模型是空的。你可以通过以下方法来避免这种奇怪的行为:

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

这有用吗?

当你传入的模型的属性为空时,MVC会有意地返回到“父”模型。显然,MVC引擎将空模型值解释为使用前一个值的意图。

稍微详细一点:ASP。NET MVC,强类型视图,部分视图参数故障

@myandmycode的答案很好,但稍微短一点的答案会是

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

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

一个解决方案是创建一个像这样的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<T>(...)匹配在Partial(...)之前,因此方便且没有歧义错误。

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

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

我创建了一组扩展方法: https://github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs < br > 我还添加了一些方法,如果模型为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<object>模型的方法,废弃的模型也可以用Razor lambda调用,它允许你用一些html包装部分结果。

如果你喜欢,可以随意使用。

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

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

我的解决方法是:


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