ASP.NET MVC - Установить ViewData для главной страницы в базовом контроллере - PullRequest
28 голосов
/ 10 июня 2009

Я использую мастер-страницу в своем проекте ASP.NET MVC. Эта мастер-страница ожидает присутствия некоторых ViewData, которые отображают это на каждой странице.

Если я не установил этот ключ ViewData в моих контроллерах, я получаю сообщение об ошибке, что он не может его найти. Однако я не хочу устанавливать ViewData в каждом контроллере (я не хочу говорить ViewData["foo"] = GetFoo(); в каждом контроллере).

Итак, я думал об установке этого в базовом контроллере, и каждый контроллер наследовал от этого базового контроллера. В конструкторе по умолчанию базового контроллера я установил ViewData. Я нашел подобный подход здесь: http://www.asp.net/learn/MVC/tutorial-13-cs.aspx. Пока все хорошо, это работает ... но проблема в том, что эти данные откуда-то из базы данных.

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

Я также не хочу передавать правильный класс Repository (или DataContext, как бы вы его ни называли) каждому контроллеру, который, в свою очередь, передает его контроллеру по умолчанию, который я затем мог бы посмеять над моими модульными тестами. Контроллеры, в свою очередь, полагаются на другие классы репозитория, и я бы в итоге передал несколько параметров конструктору. Слишком много работы для моих чувств, или я ошибаюсь? Есть ли другое решение?

Я пытался использовать StructureMap, но в итоге я не чувствовал, что это решит мою проблему, поскольку каждый контроллер все равно должен будет вызывать базовый конструктор, который инициализирует класс репозитория, поэтому я не могу издеваться.

Этот является аналогичным вопросом, но я не нашел удовлетворительного ответа. Могу ли я решить эту проблему аккуратно, возможно, используя StructureMap в качестве решения? Или мне просто сосать его, передавать репозиторий каждому контроллеру и снова передавать его базовому контроллеру? Опять же, кажется, что так много работы для чего-то такого простого Спасибо!

1 Ответ

45 голосов
/ 10 июня 2009

вижу два варианта:

Первый:

Установите ViewData для MasterPage в YourBaseController.OnActionExecuting () или YourBaseController.OnActionExecuted ():

public class YourBaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Optional: Work only for GET request
        if (filterContext.RequestContext.HttpContext.Request.RequestType != "GET")
            return;

        // Optional: Do not work with AjaxRequests
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            return;

        ...

        filterContext.Controller.ViewData["foo"] = ...
    }
}

Второе:

Или создать собственный фильтр:

public class DataForMasterPageAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Optional: Work only for GET request
        if (filterContext.RequestContext.HttpContext.Request.RequestType != "GET")
            return;

        // Optional: Do not work with AjaxRequests
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            return;

        ...

        filterContext.Controller.ViewData["foo"] = ...
    }
}

и затем примените к своим контроллерам:

[DataForMasterPage]
public class YourController : YourBaseController
{
    ...
}

Я думаю, что второе решение именно для вашего случая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...