DisplayTemplate被忽略(covarient接口?)

时间:2014-05-27 10:18:32

标签: c# asp.net-mvc razor display-templates

这很奇怪。我有以下视图文件(Views/Search/Submit.cshtml):

@model IEnumerable<KeyValuePair<string, ISearchProvider>>

@foreach (var provider in Model)
{
    var results = provider.Value.Results.Take(10);

    if (results.Count() > 0)
    {
        <text><li class="dropdown-header">@provider.Key</li></text>
        @Html.DisplayFor(x => results)   
    }
}

...其中resultsSystem.Collections.Generic.IEnumerable<out T>T is ISearchMatch

然后我在Views/Search/DisplayTemplates/SiteSearchMatch.cshtml;

中定义了一个显示模板
@model SiteSearchMatch
<li>@Html.ActionLink(Model.Name, "details", "site", new { Id = Model.Id }, null)</li>

...而SiteSearchMatch实现ISearchMatch就像这样;

public class SiteSearchMatch: ISearchMatch
{
    public int Id { get; set; }
    public string Name { get; set; }
}

我希望我的显示模板得到使用;但事实并非如此。相反,我看到输出的输出是;

<li class="dropdown-header">sites</li>
11147166811481897189813271028

...其中该数字字符串是我想通过显示模板呈现的Id的所有ISearchMatch的组合。

似乎Razor只是使用类中定义的第一个属性渲染ISearchMatch;如果我删除了Id属性的定义,我会看到Name的所有ISearchMatch的组合。


有谁知道为什么会这样,以及我如何让Razor使用我指定的显示模板?

2 个答案:

答案 0 :(得分:1)

您的期望是错误的:

  

我希望我的显示模板得到使用;但它没有。

您看到的输出是简单列出的ID。我怀疑你的ISearchMatch - 接口只公开Id - 属性,但这没关系。重要的是结果实例的实际类型。在您的情况下,以下行:

@Html.DisplayFor(x => results)

可以隐式评估为

HtmlHelper<IEnumerable<KeyValuePair<string, ISearchProvider>>>
    .DisplayFor<IEnumerable<KeyValuePair<string, ISearchProvider>>, IEnumerable<ISiteMatch>>
        (Func<IEnumerable<KeyValuePair<string, ISearchProvider>>, IEnumerable<ISiteMatch>> expression);

看起来很复杂,但基本上它只是对模型和表达式结果的隐式替换。您的模型类型为IEnumerable<KeyValuePair<string, ISearchProvider>>。这也是lampda表达式输入的类型。结果是IEnumerable<ISiteMatch>类型。这就是重要的事情!

DisplayFor实现检查结果类型是否可枚举。如果没有,它将搜索该类型的拟合模板,否则它将遍历元素并对所有元素执行此操作。 1

根据类型名称搜索模板。在您的情况下,模板使用枚举类型的名称,即ISearchMatch。它没有找到任何显示模板,所以它只是转储属性,导致你看到的内容:

11147166811481897189813271028

要解决此问题,您需要先将结果集转换为正确的类型。你可以用不同的方式做到这一点。您可以投射提供者结果的整个结果:

var results = provider.Value.Results
    .Cast<SiteSearchMatch>()
    .Take(10);

或者你在lamda表达式中单独投射它们:

@Html.DisplayFor(x => (SiteSearchMatch)results)

重要的是,标量结果类型与显示模板中的模型相同。

1 请注意,这有点复杂,例如,扩展程序还会跟踪索引并将其应用于输出,以便模型可以绑定到回发目的。

答案 1 :(得分:0)

lame 的答案是&#34; Build Action&#34;在我的观看文件Views/Search/DisplayTemplates/SiteSearchMatch.cshtml上设置为&#34;无&#34;而不是&#34;内容&#34;。

这意味着在Visual Studio中以调试模式运行时代码运行正常,但在进行任何部署时无法正常工作。

重申一下;此修复程序需要代码更改。只需更改&#34; Build Action&#34;回到&#34;内容&#34;。