Создайте макет ViewModel на основе идентификатора из URL с MVC - PullRequest
1 голос
/ 22 января 2020

Мне нужно создать ViewModel для веб-приложения моего макета. Я пробовал это решение , но оно не основано на идентификаторе URL-адреса, полученном из URL-адреса для создания ViewModel макета.

Я попробовал это, но у меня сначала была ошибка несуществующего пустого контроллера, затем я попытался включить идентификатор в качестве параметра, но я получаю ошибку «Ссылка на объект не установлена ​​для экземпляра объекта». потому что LayoutColorRGB не установлен.

public MobileController(int id)
{
    Event model = db.Events.Where(s => s.Id == id).FirstOrDefault();

    LayoutVM = new LayoutVM()
    {
        EventId = model.Id,
        LayoutColorRGB = model.LayoutColorRGB,
        SponsorLogoLink = model.SponsorLogoLink,
        SponsorLogoURL = model.SponsorLogoURL
    };

    ViewData["LayoutVM"] = LayoutVM;
}

Ответы [ 2 ]

2 голосов
/ 26 января 2020

Существует много случаев, когда необходимо извлечь данные на основе контекста запроса и показать что-то на страницах макета. Например:

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

Для этого вы можете рассмотреть следующие моменты:

  • Частичное представление: Вы можете создать несколько небольших частичных видов для тех деталей, которые имеют конкретную модель c для каждого частичного вида, и отобразить их на странице макета.

  • Использование контекста для получения данных: Вы можете инициализировать модель, извлекая информацию из Request, ViewContext, RouteData, ValueProvider и других объектов контекста.

  • Доступ к данным HTML Помощники: Вы можете создать HtmlHelper для получения данных из контекста и использования помощника в макете или частичных представлениях.

  • Доступ к данным путем внедрения зависимости: Вы можете определить некоторые службы для извлечения данных, а затем внедрить эти данные на страницы макета. В сервисе вы будете инициализировать модель, используя контекстные объекты. Если вы используете ASP. NET CORE, это хороший способ для go.

  • Доступ к данным как свойство базового контроллера : Вы можете иметь свойство в базовом контроллере и инициализировать его в конструкторе контроллера или в OnActionExecuting. Затем в макете получите свойство, приведя ViewContext.Controller к типу вашего базового контроллера и прочитав свойство.

  • Доступ к данным с помощью ViewBag : Вы можете инициализировать экземпляр модели в конструкторе базового контроллера или в методе OnActionExecuting базового контроллера, а затем положить его в ViewBag. Тогда вы можете легко использовать его в поле зрения.

  • Страницы макета: Не забудьте, что вы можете определять разные страницы макета и использовать разные макеты в зависимости от ваших требований. Вы можете установить макет в действии или в _ViewStart.

Пример

Попытка определить идентификатор в каждом запросе означает, что вам нужно иметь идентификатор как часть всех запросов, или вам нужно знать, что делать в отсутствие идентификатора. Учитывая этот факт и упрощая простоту для минимального примера, я определю следующую модель и базовый контроллер и попытаюсь разрешить идентификатор в методе OnActionExecuting базового контроллера, а затем выведу все мои контроллеры, которым необходимо такое поведение, из этого базовый контроллер.

Вы можете сделать то же самое, используя ActionFilter или фильтр глобальных действий метода OnActionExecuting вашего контроллера.

Используя следующий код:

  • Если вы просматриваете /home/index, вы увидите красную полосу внизу страницы.
  • Если вы просматриваете /home/index/1 внизу страницы вы увидите синюю полосу
  • Если вы просматриваете /home/index/2, то внизу страницы увидите зеленую полосу

Layout Model

public class LayoutViewModel
{
    public int? Id { get; set; }
    public string Color { get; set; }
}

Базовый контроллер

public class BaseControllr : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //Get the id from route
        var id = int.TryParse(ValueProvider.GetValue("id")?.AttemptedValue, out var temp)
            ? temp : default(int?);
        var model = new LayoutViewModel();

        //Your logic to initialize the model, for example
        model.Id = id;
        if (model.Id == null)
            model.Color = "FF0000";
         else if (model.Id%2==0)
            model.Color = "00FF00";
        else
            model.Color = "0000FF";

        //Set ViewBag
        ViewBag.MainLayoutViewModel = model;
        base.OnActionExecuting(filterContext);
    }
}

Домашний контроллер

public class HomeController : BaseControllr
{
    public ActionResult Index(int? id)
    {
        return View();
    }
} 

_Layout .cs html

Затем в _Layout.cshtml добавьте следующий код перед закрытием тега <body/> для проверки:

@{ 
    string color = ViewBag.MainLayoutViewModel?.Color;
    int? id = ViewBag.MainLayoutViewModel?.Id;
}
<div style="background-color:#@color;">
    Id:@id
</div>
0 голосов
/ 22 января 2020

У вас должно быть значение по умолчанию для каждого свойства вашего макета. Тогда, если ваша модель не имеет какого-либо свойства, вы можете использовать его из макета по умолчанию.

internal static readonly LayoutVM defaultLayout = new LayoutVM()
{
    EventId = 0,
    LayoutColorRGB = "#FFFFFF",
    SponsorLogoLink = "AnyLink",
    SponsorLogoURL = "AnyImageUrl"
};

public MobileController(int id)
{

    Event model = db.Events.Where(s => s.Id == id).FirstOrDefault();

    if (model == null)
    {
        ViewData["LayoutVM"] = defaultLayout;
        return;
    }

    LayoutVM = new LayoutVM()
    {
        EventId = model.Id,
        LayoutColorRGB = model.LayoutColorRGB ?? defaultLayout.LayoutColorRGB,
        SponsorLogoLink = model.SponsorLogoLink ?? defaultLayout.SponsorLogoLink,
        SponsorLogoURL = model.SponsorLogoURL ?? defaultLayout.SponsorLogoURL
    };

    ViewData["LayoutVM"] = LayoutVM;
}
...