C # Централизация повторяющихся данных VIewData в MVC

Когда пользователь входит в мое приложение, я хочу, чтобы его имя отображалось во всем приложении. Я использую фреймворк asp.net MVC. Но я не хочу, чтобы каждый контроллер вставлял что-то вроде:

ViewData["User"] = Session["User"];

Это потому, что вы не можете повторяться. (Я считаю, что это принцип DRY [Don't Repeat Yourself] объектно-ориентированного программирования.) ViewData [«Пользователь»] находится на моей главной странице. Итак, мой вопрос: как лучше всего обрабатывать мои ViewData ["User"] в одном месте?


person Martijn    schedule 17.04.2009    source источник


Ответы (4)


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

Например:

public class UserInfoAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(
        ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
        filterContext.Controller.ViewData["user"] = "Foo";
    }
}
...
[HandleError, UserInfo]
public class HomeController : Controller
{...}

(также может использоваться на уровне действия (метода))


или с общим базовым классом:

public abstract class ControllerBase : Controller
{
    protected override void OnActionExecuting(
        ActionExecutingContext filterContext)
    {
        ViewData["user"] = "Bar";
        base.OnActionExecuting(filterContext);
    }
}

[HandleError]
public class HomeController : ControllerBase
{...}
person Marc Gravell    schedule 17.04.2009
comment
Спасибо, попробую базовый класс. Но зачем переопределять метод OnActionExecuting ()? Что делает этот метод? Какая у этого цель? - person Martijn; 17.04.2009
comment
Он выполняется непосредственно перед выполнением вашего действия (метода). Если вы хотите, вы, вероятно, можете использовать вместо этого OnActionExecuted, которое выполняется сразу после выполнения вашего действия. - person Marc Gravell; 17.04.2009
comment
Хорошо, и поскольку я помещаю это в свой базовый класс, это влияет на все мои действия в контроллере? - person Martijn; 17.04.2009
comment
Правильный. Это также верно в отношении подхода с фильтром действий, когда вы помещаете [UserInfo] на уровень класса (а не на уровень метода). - person Marc Gravell; 17.04.2009

Прошел год, но я только что наткнулся на этот вопрос и считаю, что есть лучший ответ.

Джимми Богард описывает решение, описанное в принятом ответе, как анти-шаблон и предлагает лучшее решение, включающее RenderAction: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/18/the-filter-viewdata-anti-pattern.aspx

person Paul Suart    schedule 04.05.2010

Другой метод предоставления постоянных данных модели для всего вашего приложения - переопределение DefaultFactoryController вашим настраиваемым. В своем CustomerFactoryController вы должны наполнить ViewBag моделью, которую хотите сохранить.

person lamchakchan    schedule 16.12.2011

Создайте базовый класс для своих моделей со свойством UserName:

public abstract class ModelBase
{
    public string UserName { get; set; }
}

Создайте базовый класс для своих контроллеров и переопределите его метод OnActionExecuted. В нем проверьте, является ли модель производной от BaseModel, и если да, установите ее свойство UserName.

public class ControllerBase : Controller
{
    protected override void OnActionExecuted(
        ActionExecutedContext filterContext)
    {
        var modelBase = ViewData.Model as ModelBase;

        if (modelBase != null)
        {
            modelBase.UserName = "foo";
        }

        base.OnActionExecuted(filterContext);
    }
}

Тогда вы сможете отображать UserName пользователя в представлении следующим образом:

<%= Html.Encode(Model.UserName) %>

См. также:

person Konstantin Tarkus    schedule 17.04.2009
comment
проверьте, является ли модель производной от BaseModel и .. как мне это сделать? Вы можете привести мне пример? - person Martijn; 17.04.2009
comment
Думаю, я понял твое решение. Но разве это не сложно? Разве общий базовый класс Марка Гравелла в некотором роде не делает то же самое? - person Martijn; 17.04.2009
comment
@Martijn, он позволяет работать со строго типизированной моделью вместо словаря ViewData [..]. С его помощью вы получаете поддержку интеллекта в ваших представлениях и т. Д. И т. Д. - person Konstantin Tarkus; 17.04.2009
comment
@KonstantinTarkus - разве это не должно быть var modelBase = ViewData.Model as BaseModel;? - person DaveD; 03.02.2015