迭代从 AbstractViewModel 和 DisplayTemplates 派生的 Collection 个 ViewModels 渲染两个 DisplayTemplates

Iterating a Collection of ViewModels deriving from an AbstractViewModel and DisplayTemplates renders both DisplayTemplates

(为标题道歉..很难确定)

我遇到这样一种情况,控制器将构建一个列表,其中包含一组从抽象基础 class 派生的 ViewModel。然后我使用显示模板适当地呈现内容,但是当我导航到 url 时,它似乎将整个内容呈现两次。这是我的代码

public abstract class AbstractItemViewModel
{
}

public class TypeAViewModel : AbstractItemViewModel
{
    public int ID { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
}

public class TypeBViewModel : AbstractItemViewModel
{
    public string Title { get; set; }
    public List<string> Items { get; set; }
}

然后我的控制器构建一个这样的测试用例。

public class HomeController : BaseController
{
    // GET: Home
    public ActionResult Index()
    {
        List<AbstractItemViewModel> items = new List<AbstractItemViewModel>();

        items.Add(new TypeAViewModel() { ID = 1, Title = "Test A", Body = "This is some body content." });
        items.Add(new TypeBViewModel() { Title = "Test B", Items = new List<string>() { "Line 1", "Line 2", "Line 3" } });
        return View(items);
    }
}

... 为了完整起见,这里是基本控制器 class(没什么特别的)..

public class BaseController : Controller
{

}

.. 这是视图 ...

@using xxx.ViewModels
@model List<AbstractItemViewModel>

@{
    ViewBag.Title = "Home";
}


<h1>@Model.Count()</h1>
<div class="container">
    <div class="row">
        @foreach (AbstractItemViewModel item in Model)
        {
            <div class="col-xs-12">
                @Html.DisplayForModel(item)
            </div>
            <p>space</p>
        }
    </div>
</div>

..和2个显示模板 TypeAViewModel.cshtml

@using xxx.ViewModels
@model TypeAViewModel

<h2>@Model.Title (@Model.ID)</h2>
<p>@Model.Body</p>

..和... TypeBViewModel.cshtml

@using xxx.ViewModels
@model TypeBViewModel

<h2>@Model.Title</h2>
<ul>
    @foreach (string s in Model.Items)
    {
        <li>@s</li>
    }
</ul>

作为我得到的输出。

2

Test A (1) This is some body content.

Test B Line 1 Line 2 Line 3 space

Test A (1) This is some body content.

Test B Line 1 Line 2 Line 3 space

如您所见,它似乎将整个内容渲染了两次。我已经放置了一个断点并逐步通过索引视图,绝对不会重复这样的循环。有人看到我错过了什么吗?

你应该使用 DisplayFor Html 助手而不是 DisplayForModel,因为 DisplayForModel 发送你的整个模型(在这种情况下,传入模型的完整列表 - 的后代AbstractItemViewModel; item 实际上只是传递给模型的附加数据)到视图。实际上,对于 foreach 中的每个项目,完整的模型都会传递给您的视图;例如如果您的列表中有 3 个模型,则每个模型将被渲染 3 次(如果是 4 次,则渲染 4 次,依此类推)。

因此,要使其正常工作,请使用此助手:@Html.DisplayFor(model => item) inside foreach 语句而不是 DisplayForModel.