ASP.NET MVC - установка ViewData для главной страницы в базовом контроллере
Я использую masterpage в моем проекте ASP.NET MVC. Эта главная страница ожидает, что некоторые ViewData будут присутствовать, что отображает это на каждой странице.
Если я не устанавливаю этот ключ ViewData в своих контроллерах, я получаю сообщение об ошибке, которое он не может найти. Однако я не хочу устанавливать ViewData в каждом контроллере (я не хочу сказать ViewData["foo"] = GetFoo();
в каждом контроллере).
Итак, я подумывал установить это в базовом контроллере, и каждый контроллер наследует этот базовый контроллер. В конструкторе по умолчанию базового контроллера я устанавливаю ViewData. Я нашел аналогичный подход здесь: http://www.asp.net/learn/MVC/tutorial-13-cs.aspx. До сих пор это так хорошо, но проблема в том, что эти данные поступают из где-то в базе данных.
Теперь, когда я хочу Unit Test мои контроллеры, те, которые наследуют от базового контроллера, вызывают его конструктор по умолчанию. В конструкторе по умолчанию я инициализирую свой класс репозитория для получения этих данных из базы данных. Результат: мои модульные тесты терпят неудачу, поскольку они не могут получить доступ к данным (и я, конечно, не хочу, чтобы они обращались к этим данным).
Я также не хочу передавать правильный класс репозитория (или DataContext, независимо от того, что он назовет его) для каждого контроллера, который, в свою очередь, передает его контроллеру по умолчанию, который я мог бы затем высмеять мои модульные тесты. Контроллеры, в свою очередь, полагаются на другие классы репозитория, и я бы закончил передачу нескольких параметров конструктору. Слишком много работы для моего чувства, или я ошибаюсь? Есть ли другое решение?
Я пробовал использовать StructureMap, но в конце концов мне не хотелось, чтобы это исправляло мою проблему, поскольку каждому контроллеру все равно придется вызывать базовый конструктор, который инициализирует класс репозитория, поэтому я не могу издеваться над ним.
Этот вопрос является аналогичным, но я не нашел удовлетворительного ответа. Могу ли я решить эту проблему аккуратным способом, возможно, используя StructureMap в качестве решения? Или мне нужно сосать его и передать репозиторий каждому контроллеру и передать его снова базовому контроллеру? Опять же, похоже, что так много работы для чего-то такого простого. Спасибо!
Ответы
Ответ 1
Я вижу два варианта:
Во-первых:
Установите 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
{
...
}
Я думаю, что второе решение именно для вашего случая.