.NET Core: атрибуты ViewModel не отображаются - PullRequest
0 голосов
/ 09 мая 2018

Я занимаюсь разработкой веб-приложения ASP.NET Core 2.0 с использованием движка Razor. Прежде всего, я пытался искать решения через Интернет и здесь, в 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; }
    }
}

Как видите, свойства Name и PhoneNumber имеют указанный атрибут 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, все работает нормально. Но если я помещу его в свою пользовательскую папку Customer / Views, имя свойств не будет отображаться / отображаться, а также атрибуты проверки не будут работать вообще. Два поля ввода отображаются, потому что я вижу следующую форму: enter image description here

То, что я уже пытался решить, (но никто из них не помог):

  • Настройка местоположения просмотра при запуске

    services.Configure<RazorViewEngineOptions>(o => o.ViewLocationFormats.Add("/Customers/Views/{0}" + RazorViewEngine.ViewExtension));
    
  • Использование абсолютного пути, когда я включаю частичное представление:

    @Html.Partial("~/Customers/Views/_NewCustomer.cshtml")
    
  • Создайте папку с именем «Shared» в моей папке «Customer» и поместите туда мой частичный вид: Customer / Views / Shared

  • Удалив все папки bin и obj, очистите, а затем пересоберите решение

Кроме того, я понял, что если частичное представление находится в пользовательской папке, то VS2017 (IntelliSense) не распознает html-теги, характерные для asp-net-core, например, <form asp-controller= не выделяется зеленым, только если представление находится в общей папке.

Дополнительная информация:

Структура моей папки выглядит следующим образом: enter image description here

Как вы думаете, в чем проблема? Спасибо за любую помощь!

1 Ответ

0 голосов
/ 10 мая 2018

Не уверен, что это поможет вам решить реальную проблему, так как вам, вероятно, нужно будет многое изменить ... но я считаю эту структуру более "чистой", чем та, которая у вас есть. Проблемы, которые я сразу вижу с этим:

  • Трудно провести различие между фактическими функциями и кодом настройки / инфраструктуры. Containers - это функция или что-то связанное с Docker? Не знаю, надо его открыть.
  • Так, как сейчас, в вашем IViewLocationExpander вы должны «жестко» кодировать каждое имя функции, потому что все они распространены ... не так круто.

Я предлагаю изменить структуру на:

  • Функции (переименуйте представления в функции, сохраните папку Shared в обычном режиме.)
    • Клиент
      • Контроллеры
      • Просмотры

Затем вы настраиваете 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, и она будет автоматически выбрана. Вот изображение структуры, которую я использовал в моей настройке:

enter image description here

Редактировать: Вот мое решение на Github joaopgrassi / custom-razorview-location

Кроме того, я не совсем понимаю, как использовать ViewModels в отдельном проекте. Вся цель ViewModels состоит в том, чтобы обслуживать пользовательский интерфейс. Там нет ничего DDD на ViewModels, с общедоступными сеттерами. Может быть, я неправильно понял вас ... но я бы определенно посмотрел на это. DDD - это богатые, очень часто неизменяемые сущности ... а ViewModels - это просто классы poco просто для передачи данных.

...