Razor MVC, где можно разместить глобальные переменные, доступные на главной странице, частично или частично? - программирование
Подтвердить что ты не робот

Razor MVC, где можно разместить глобальные переменные, доступные на главной странице, частично или частично?

Здравствуйте, Razor MVC Gurus:

Новый вопрос.

Фон. У меня есть пользовательский параметр IIdentity, который установлен в HttpModule, прежде чем он попадает в контроллер и представления. Чтобы использовать его, я должен сделать

   MyIdentity myIdentity = (MyIdentity)((GenericPrincipal)context.User).Identity;
   MyComplexUser user = myIdentity.User;
   //user.name //user.location //user.username  //etc

Проблема заключается в том, что я использую объект в разных местах, например

  • мастер-макет
  • Некоторые вложенные макеты на уровне уровня
  • Некоторые частичные просмотры
  • Некоторые представления

Это зависит от того, какие свойства объекта MyComplexUser нужны для просмотра.

В настоящее время во взглядах мне нужно сделать это очень сложное кастинг, чтобы добраться до свойства. Например, если я хочу "Имя" пользователя, мне нужно сделать

@(((MyComplexUser) (((MyIdentity) ((GenericPrincipal) context.User).Identity).user)). Имя)

Я предполагаю, что могу поместить его в контроллеры, а затем заполнить ViewBag с помощью свойства ViewBag.MyUser, но затем

  • Мне не нравится использовать ViewBag. Я предпочитаю строго типизированные объекты
  • Если я использую строго типизированный объект ( "MyUser" ) для представлений, тогда я должен популяризовать все эти модели с свойством "MyUser" . Чувствуешь себя немного грязным? Поскольку мне нравится сохранять мои модели в чистоте и быть конкретными для тех взглядов, с которыми они связаны. Кроме того, он становится излишне повторяющимся.
  • В таких местах, как master_layout.cshtml или partialviews, как вы получаете доступ к "MyUser" , если я помещаю их в контроллер?
  • Использовать RenderAction и создавать частичные просмотры для каждого свойства User является излишним?

Спасибо. Опять же, я новичок в MVC 4, любое предложение очень ценит это.

4b9b3361

Ответ 1

Я объясню аналогичное решение, которое очень хорошо работает для меня. С небольшими изменениями, я считаю, что это сработает для вас (и других, надеюсь).

В принципе, мы будем использовать наследование.

Контроллеры

Создайте настраиваемый базовый контроллер, например

public class BaseController : Controller

и изменим наши контроллеры на наследование от него, как

public class HomeController : BaseController

Модели (ViewModels, я говорю)

Вероятно, у вас много классов в папке "Модели", верно? Они действуют как DTOs от контроллера к представлениям, right²? Если вы ответили "да" для обоих, продолжайте читать.

Позвольте создать базовый класс модели, например public class BaseVM, и пусть наши модели наследуют от него, например public class HomeIndex : BaseVM

Важно: ваш файл макета (_Layout или вообще любой) должен быть строго типизирован для BaseVM или его дочернего элемента.

Крючок

Теперь, когда все красиво напечатано, позвольте использовать конвейер запроса в нашу пользу. В BaseController вы добавите метод, который выглядит следующим образом:

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
    if (filterContext.Result is ViewResultBase)//Gets ViewResult and PartialViewResult
    {
        object viewModel = ((ViewResultBase)filterContext.Result).Model;

        if (viewModel != null && viewModel is BaseVM)
        {
            BaseVM baseVM = viewModel as BaseVM;

            baseVM.MyIdentity = (MyIdentity)((GenericPrincipal)context.User).Identity;
            //and so on...
        }
    }

    base.OnActionExecuted(filterContext);//this is important!
}

OnActionExecuted называется после выполнением действия, но до рендеринга представления. Это именно то, что мы хотим.

Надеюсь, ты это уже понял. =)