繁体   English   中英

ASP.NET Core 2中的HTML.DisplayFor接口视图模型

[英]Html.DisplayFor interface viewmodel in ASP.NET Core 2

我很难弄清楚如何为接口类型viewmodel渲染显示模板。 假设我有一个像下面这样的视图模型:

public class DashboardViewModel
{
    public ISelectedWalletsViewModel Wallets { get; set; }
}

public interface ISelectedWalletsViewModel
{
}

public class OneSelectedWalletViewModel : ISelectedWalletsViewModel
{
    public SelectedWalletViewModel SelectedWallet { get; set; }
    public IEnumerable<WalletViewModel> OtherWallets { get; set; }
}

public class AllSelectedWalletsViewModel : ISelectedWalletsViewModel
{
    public IEnumerable<WalletViewModel> Wallets { get; set; }
}

public interface IWalletViewModel
{
    long Id { get; set; }
    string Name { get; set; }
    string Description { get; set; }
    string CurrentBalance { get; set; }
}

public class WalletViewModel : IWalletViewModel
{
    public long Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string CurrentBalance { get; set; }
}

public class SelectedWalletViewModel : IWalletViewModel
{
    public long Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string CurrentBalance { get; set; }
}

因此,我创建了DisplayTemplates文件夹来为每个模型设置相应的.cshtml文件:

<!-- START OneSelectedWalletViewModel.cshtml -->
@using CLSoft.MyWallet.Models.Home
@model OneSelectedWalletViewModel

@Html.DisplayFor(m => m.SelectedWallet)
@Html.DisplayFor(m => m.OtherWallets)
<a asp-action="Index">Select all wallets</a>
<!-- END OneSelectedWalletViewModel.cshtml -->

<!-- START AllSelectedWalletsViewModel.cshtml -->
@using CLSoft.MyWallet.Models.Home
@model AllSelectedWalletsViewModel

@Html.DisplayFor(m => m.Wallets)
<!-- END AllSelectedWalletsViewModel.cshtml -->

<!-- START SelectedWalletViewModel.cshtml -->
@using CLSoft.MyWallet.Models.Home
@model SelectedWalletViewModel

<div class="card border-primary">
    <div class="card-body">
        <h5 class="card-title">@Model.Name</h5>
        <h6 class="card-subtitle mb-2 text-muted">@Model.CurrentBalance</h6>
        <p class="card-text">@Model.Description</p>
    </div>
</div>
<!-- END SelectedWalletViewModel.cshtml -->

<!-- START WalletViewModel.cshtml -->
@using CLSoft.MyWallet.Models.Home
@model WalletViewModel

<div class="card">
    <div class="card-body">
        <h5 class="card-title">@Model.Name</h5>
        <h6 class="card-subtitle mb-2 text-muted">@Model.CurrentBalance</h6>
        <p class="card-text">@Model.Description</p>
        <a asp-action="Index" asp-route-wallet-id="@Model.Id">select wallet</a>
    </div>
</div>
<!-- END WalletViewModel.cshtml -->

现在我只缺少控制器的动作方法:

[HttpGet]
public async Task<IActionResult> Index(long? walletId)
{
    var viewModel = await _service.GetDashboardViewModelAsync(walletId);
    return View(viewModel);
}

和Index.cshtml查看代码:

@using CLSoft.MyWallet.Models.Home
@model DashboardViewModel

@{
    ViewData["Title"] = "Index";
}

<div class="row">
    <div class="col">
        <h4>Your wallets</h4>
        @Html.DisplayFor(m => m.Wallets)
    </div>
</div>

现在我应该一切就绪了。 事情是没有标记被渲染。 在测试期间,我尝试为接口ISelectedWalletsViewModel添加显示模板

@model ISelectedWalletsViewModel
@Html.DisplayForModel()

在@ Html.DisplayForModel()上设置一个断点,然后-ta dah! -调试器应停止。 但是,可惜,没有调用任何具体的DisplayTemplate。 我想念什么吗?

编辑1 :我创建了一个github仓库来显示问题。

编辑2 :我也报告了AspNet / Mvc存储库上的问题

原来这是设计使然。 我将在下面引用NTaylorMullen的答案,以防链接消失(不太可能,但仍然):

[...]关于这个问题,实际上是设计使然。 转到Core时,我们发现在旧版ASP.NET中,我们有过度共享的习惯(使用意外的视图模型模板)。 为了解决这个问题,我们删除了该功能,并要求用户在使用显示模板时明确使用的类型。 抱歉,您没有更好的答案!

因此,您应该如何重构代码以满足这些规则?

  1. [不太好]您可以将ViewModels重构为一个包含所有可能实现的视图模型,并在Views代码中使用if语句来呈现所需的视图;
  2. [更好],您可以重构控制器动作逻辑以处理ViewModel的所有可能实现,并提供所需的View。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM