首页 > 解决方案 > .NET Core:不呈现 ViewModel 属性

问题描述

我正在使用 Razor 视图引擎开发 ASP.NET Core 2.0 Web 应用程序。首先,我试图通过互联网和 StackOverFlow 寻找解决方案,但其中任何一个都可以解决我的问题。让我们看看我们面临着什么:

我有一个相对简单的客户视图模型:

namespace MokaKukaMap.Application.Customers.ViewModels.Models
{
    public class CustomerViewModel
    {
        public long Id { get; set; }

        [Display(Name = "Név")]
        [Required]
        public string Name { get; set; }

        [Display(Name = "Telefonszám")]
        [Required]
        public string PhoneNumber { get; set; }
    }
}

如您所见,NameandPhoneNumber属性具有Display指定的属性。我相应的部分视图 ( _NewCustomer.cshtml) 如下:

@model MokaKukaMap.Application.Customers.ViewModels.Models.CustomerViewModel

<div class="col-lg-5 basic-surronder">
    <form asp-controller="NewCustomer" asp-action="NewCustomer" class="well">
        <div id="form-horizontal">
            <div class="form-group">
                <label asp-for="@Model.Name" class=""></label>
                <div class="">
                    <input asp-for="@Model.Name" class="form-control">
                    <span asp-validation-for="@Model.Name" class="text-danger"> </span>
                </div>
            </div>

            <div class="form-group">
                <label asp-for="@Model.PhoneNumber" class=""></label>
                <div class="">
                    <input asp-for="@Model.PhoneNumber" class="form-control">
                    <span asp-validation-for="@Model.PhoneNumber" class="text-danger"> </span>
                </div>
            </div>
        </div>
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div class="form-group">
            <div class="">
                <input type="submit" formnovalidate="formnovalidate" value="Új ügyfél hozzáadása" class="btn btn-primary" />
            </div>
        </div>
    </form>
</div>

到目前为止,一切都很好。正如我已经提到的,我将此视图用作局部视图,因此我将她包含在NewCustomer.cshtml主视图中,并带有以下行:

@Html.Partial("_NewCustomer")

位于_NewCustomer.cshtml标准 Views/Shared 文件夹中。我想做的是将此部分视图放入特定文件夹,即Customers/Views 文件夹。为了解决这个问题,我做了一个CustomerViewLocationExpander,如下所示:

public class CustomViewLocationExpander : IViewLocationExpander
{
    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        var viewLocationFormats = new[]
        {
            "~/Customers/Views/{0}.cshtml", 
            "~/Views/Shared/{0}.cshtml",
            "~/Views/{0}.cshtml",
        };
        return viewLocationFormats;
    }

    public void PopulateValues(ViewLocationExpanderContext context)
    {
        context.Values["customviewlocation"] = nameof(CustomViewLocationExpander);
    }
}

在 Startup.cs 中配置:

    services.Configure<RazorViewEngineOptions>(options => options.ViewLocationExpanders.Add(new CustomViewLocationExpander()));

我的问题如下:如果_NewCustomer.cshtml位于 Views/Shared 文件夹中,一切正常。但是,如果我将它放在我的自定义客户/视图文件夹中,则不会显示/呈现属性的名称,并且验证属性也根本不起作用。呈现两个输入字段是因为我看到以下表单: 在此处输入图像描述

我已经尝试解决我的问题,(但他们都没有帮助):

此外我意识到,如果部分视图位于自定义文件夹中,那么 VS2017 (IntelliSense) 无法识别 asp-net-core 特定的 html 标签,例如<form asp-controller=只有当视图位于共享文件夹。

附加信息:

我的文件夹结构如下所示: 在此处输入图像描述

你觉得问题出在哪里?谢谢你的帮助!

标签: c#razorasp.net-core

解决方案


不确定这是否会帮助您解决实际问题,因为您可能需要更改很多东西。但我发现这种结构比您那里的结构更“干净”。我立即看到的问题是:

  • 很难区分实际功能和设置/基础代码。是Containers一个特性还是与 Docker 有关?不知道,必须打开它。
  • 现在的方式是,IViewLocationExpander您必须对每个功能名称进行“硬编码”,因为它们都散布在各处……不太酷。

我的建议是将结构更改为:

  • 功能(将视图重命名为功能,正常保留共享文件夹。)
    • 顾客
      • 控制器
      • 意见

然后,你ViewLocationExpander像这样配置你:

public class ViewLocationExpander : IViewLocationExpander
{

   public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        // {1} is Controller, {0} is View Name
        return new [] 
        {
            "/Features/{1}/Views/{0}.cshtml", // Finds the Customer View folders
            "/Features/{1}/{0}.cshtml", // finds the Home views.. they are in root of the folder.. so no need for Views
            "/Features/Shared/{0}.cshtml" // Layouts
        };
    }

    public void PopulateValues(ViewLocationExpanderContext context)
    {

    }
}

这样,您可以Product使用它自己的Views文件夹添加新功能,例如,它会自动被拾取。这是我在设置中使用的结构的图像:

在此处输入图像描述

编辑:这是我在 Github joaopgrassi/custom-razorview-location上的解决方案

另外,我真的不明白在一个单独的项目中拥有 ViewModel 的意义。ViewModel 的全部目的是为 UI 服务。ViewModel 上没有任何 DDD,带有公共设置器。也许我误解了你..但我肯定会更深入地研究。DDD 是丰富的,通常是不可变的实体。而 ViewModel 只是 poco 类,只是为了传输数据。


推荐阅读