Как установить глобальные viewmodels в ASP .NET Core 3.1?

#asp.net-core-mvc #asp.net-core-3.1 #asp.net-mvc-viewmodel

#asp.net-core-mvc #asp.net-core-3.1 #asp.net-mvc-viewmodel

Вопрос:

Я новичок в ASP.NET Core и имеют некоторые проблемы с привязкой глобальных моделей и viewmodels к представлениям razor. Мое приложение представляет собой смесь веб-API и MVC с представлениями razor.

Моя цель

Когда я открываю ASP.NET На странице MVC мне нужно создать экземпляр модели, загрузив ее из базы данных ( DbContext сервиса) на основе идентификатора, полученного в файле cookie. Я хочу использовать этот объект модели глобально в каждом представлении или частичном представлении.

Текущая реализация

Я могу получить доступ к файлам cookie в методах действий контроллеров страниц, так что мне нужно загружать модель из DbContext в каждом методе действия и привязывать ее как viewmodel к целевому представлению. Это непрактично, потому что я должен делать это в каждом контроллере страницы, потому что мне нужен этот объект модели на всех страницах в моей панели навигации.

Идея

Я думаю, что должна быть возможность доступа к файлам cookie и dbcontext в Startup.cs и привязать объект модели к _ViewStart.cshtml, чтобы он был доступен глобально в каждом представлении или частичном представлении. Даже этот подход был правильным, я понятия не имею, как будет выглядеть код. Потому что я изучаю веб-приложения с .NET Core, изучая на практике и пробуя и ошибаясь в данный момент. 🙁

Обновить

У меня есть страница макета _Layout.cshtml , которая включает частичные представления, такие как _NavPane.cshtml . Моя цель — передать объект модели в _Layout, экземпляр которого создается путем загрузки из базы данных (у меня есть сервис IMandantRepository для этой цели) и зависит от файла cookie.

Этот объект модели необходим при каждом запросе страницы. Вот почему было бы лучше загружать объект модели вне контроллеров страниц MVC и передавать его им (что я не могу реализовать технически).

Я попытался найти решение самостоятельно и в итоге получил следующее промежуточное уродливое решение. Ниже приводится содержимое _ViewStart файла. Внизу я назначаю необходимые глобальные переменные, которые я могу использовать в каждом представлении или частичном представлении.

Это решение имеет как минимум два недостатка:

  1. Возможно, объект модели загружен избыточно.
  2. Слишком много программной логики в файле представления.
     @inject MyProject.Data.IMandantRepository mandantRepo
    @{
    // Main layout template
    Layout = "_Layout";

    // Define default values
    bool showAdminSection = false;
    string src = "/images/logos/nologo.png";

    // Read cookie value
    string currentMandantUid;
    Context.Request.Cookies.TryGetValue("currentMandant", out currentMandantUid);
 
    // Load mandant from the database
    var thisMandant = mandantRepo.GetMandantByUid(currentMandantUid);
    if(thisMandant is Mandant){
        src = "data:image/*;base64,"   thisMandant.GetBase64Logo();
        showAdminSection = thisMandant.Abbr == "AdminMandant";
    }

    // Assing global variables to ViewData
    ViewData["CurrentMandant"] = thisMandant;
    ViewData["logoSrc"] = src;
    ViewData["showAdminSection"] = showAdminSection;
}
 

Комментарии:

1. I need that model object on all pages in my navigation page Вы пытались поместить навигацию на страницу макета? Если вы хотите создать навигацию на основе данных, хранящихся в БД, вы можете реализовать и использовать пользовательский сервис для запроса данных, затем вы можете вызвать эту службу в layout и предоставить данные для меню навигации.

2. @FeiHan Спасибо за ваш ответ. Я обновил свой вопрос небольшим объяснением о макете представления и моем промежуточном решении. Идеальным решением для меня было бы загрузить объект модели вне контроллеров страниц MVC и передать его в контроллер страницы и представление макета или использовать его глобально.

Ответ №1:

Это пример кода в ConfigureService() of Startup.cs . Вы можете зарегистрировать свой dbContext класс таким образом.

 services.AddDbContext<BookStoreContext>( options =>
        options.UseSqlServer(_configuration.GetConnectionString("DefaultConnection")));
 

Комментарии:

1. Спасибо за ваш ответ. Я обновил свой вопрос промежуточным решением, что не является лучшей практикой. Я думаю, лучшим решением может быть следующее с помощью метода Confiure() в Startup.cs string mycookie = app. Службы приложений. GetService<HttpContextAccessor>().HttpContext.Request. Cookies[‘MyCookie’]; var MyModel = приложение. Службы приложений. GetService<IMandantRepository>().GetMandantByAbbr(mycookie); // Как внедрить MyModel в _Layout.cshtml или получить к нему доступ из _Layout.csthml???

2. Забудьте идею о добавлении кода в Startup.cs в моем последнем комментарии. Это ошибка новичка. Методы запуска выполняются только один раз, при запуске хоста веб-приложения. 🙂 Я считаю, что мне нужно промежуточное программное обеспечение, которое считывает cookie и устанавливает объект глобальной модели. Но открытый вопрос заключается в том, как передать глобальный объект в _Layout.cshtml…