Куда должна идти логика «Master Page» в MVC? - PullRequest
3 голосов
/ 07 марта 2009

Я экспериментирую с MVC, и мой вопрос - , где у меня была логика Page_Load в главных страницах с веб-формами, куда она должна идти в MVC? Вот бизнес-пример:

  • Различные заголовки хоста должны приводить к отображению разных заголовков страниц на (одной) главной странице сайта, следовательно, на всех страницах. Например, если заголовок хоста - hello.mydomain.com, заголовок страницы должен быть «Hello World» для всех страниц / просмотров, а goodbye.mydomain.com должен быть «Goodbye World» для всех страниц / просмотров.
  • Если заголовок узла отличается от того, что есть в списке, независимо от того, где находится приложение, его следует перенаправить в /Error/NoHostHeader.

Раньше я помещал это в событие MasterPage Load (), и, похоже, в MVC я мог делать это либо на каждом контроллере (не правильно вызывать эту функцию на каждом контроллере), или где-то в Global.asax (кажется слишком ... глобальным?).

Редактировать: Я получил это для успешной работы, используя метод Global.asax в сочетании с контроллером для фактической обработки данных. Единственной проблемой на данный момент является то, что вся информация заголовка узла находится в базе данных. Обычно я храню информацию об «арендаторе», если вы используете переменную Session и выполняете вызов БД только тогда, когда ее там нет; Есть ли лучший способ сделать это?

Ответы [ 4 ]

9 голосов
/ 07 марта 2009

По какой-то причине в MVC нет эквивалента 1: 1, давайте просто повторим, как думать об этом в MVC:

Модель : "Страницы этого сайта всегда запрашиваются в определенном контексте, назовем его арендатором (или пользователем, темой или чем-либо еще, что представляют ваши поддомены). Модель домена имеет свойство, представляющее арендатор текущего запроса. "

Просмотр : «Визуализация заголовка страницы в зависимости от клиента, установленного в модели.»

Контроллер : «Установить владельца в модели в зависимости от заголовка узла».

Имейте в виду, что мы хотим избежать смешивания контроллера, представления и бизнес-логики. Наличие логики контроллера в более чем одном месте или месте, которое не называется «контроллером», не является проблемой, если оно остается разделенным.

А теперь хорошая вещь: Вы можете сделать этот "стиль MVC" даже с веб-формами , и решение по-прежнему работает с ASP.NET MVC!

У вас все еще есть жизненный цикл запроса (не жизненный цикл страницы), поэтому вы можете реализовать собственный HttpModule, который содержит эту часть логики контроллера для всех запросов. Он обрабатывает событие BeginRequest, проверяет заголовок узла и сохраняет владельца в чем-то вроде HttpContext.Current.Items ["tenant"]. (Конечно, вы могли бы иметь статическую, типизированную оболочку для этой словарной статьи.)

Тогда все ваши объекты модели (или базовый класс модели, или все, что подходит для вашего решения) могут получить доступ к HttpContext, чтобы обеспечить доступ к этой информации, например так:

public string Tenant
{
    get { return HttpContext.Current.Items["tenant"]; }
}

Преимущества:

  • Вы разделили причину (заголовок хоста) и следствие (отображение заголовка страницы), улучшая удобство сопровождения и тестируемость
  • Поэтому вы можете легко добавить дополнительное поведение в модель вашего домена на основе этого состояния, например, загрузку содержимого из базы данных в зависимости от текущего арендатора.
  • Вы можете легко сделать так, чтобы большее количество частей представления зависело от арендатора, например, от CSS-файла, логотипа и т. Д.
  • Позже вы можете изменить логику контроллера, чтобы установить арендатора в модели не только на основе поддоменов, но, возможно, на основе файла cookie, реферера, термина поиска, языка пользовательского агента или того, о чем вы можете думать, без изменение любого вашего кода в зависимости от модели.

Обновление для редактирования : мне не нравится идея сохранения состояния в сеансе, особенно если ваш файл cookie сеанса может применяться не только к каждому поддомену, но и ко всем доменам. В этом случае вы можете показывать несогласованный контент, если ранее пользователи просматривали другой поддомен. Вероятно, информация в базе данных, которая сопоставляет заголовки хоста с арендаторами, будет меняться не очень часто, поэтому вы можете ее кэшировать и вам не нужен поиск в базе данных для каждого запроса.

3 голосов
/ 07 марта 2009

Вы тоже думаете "WebForms" и не хватает MVC. Главная страница - это просто оболочка вашего представления, и она должна содержать только HTML-разметку. Вы можете отправлять вещи своему хозяину, но это дорога в один конец, и вы должны стремиться к агностическим взглядам. Итог: забудьте о событиях, которые имели WebForms, так как они здесь не будут использоваться.

Так как вы имеете дело с заголовками хоста, я полагаю, вы могли бы поместить их в Global.asax ... отлично, теперь я запутался:

украденный код от http://forums.asp.net/t/1226272.aspx

protected void Application_BeginRequest(object sender, EventArgs e)
        {
            string host = string.Empty;

            if (this.Request.ServerVariables["HTTP_HOST"] == this.Request.Url.DnsSafeHost)
            {
                host = this.Request.Url.DnsSafeHost;
            }
            else
            {
                Regex regex = new Regex("http://[^/]*.host/([^/]*)(/.*)");
                Match match = regex.Match(this.Request.Url.AbsoluteUri);

                if (match.Success)
                {
                    host = match.Groups[1].Value;
                    Context.RewritePath(match.Groups[2].Value);
                }
            }

            // Match the host with the portal in the database
            ...
        } 
3 голосов
/ 07 марта 2009

Вы можете создать базовый контроллер, который предоставил правильные ViewData для вашего просмотра главной страницы MVC, а затем получить из них каждый из ваших реальных контроллеров. Если вы поместите логику в метод ActionExecuting, вы сможете создать исключение или перенаправить на страницу ошибки, если это необходимо.

2 голосов
/ 17 августа 2011
...