При попытке уменьшить размер моих MVC-контроллеров я реорганизую много логики в сервисы (хотя эта же проблема будет применяться, если она будет учитываться в моделях). Я часто находя, что я непосредственно установка ViewData
и/или TempData
с информацией я хотел отображаться пользователю, например:Хорошо ли передавать TempData и/или ViewData в службы?
var repoUser = new UserRepository();
var foundUser = repoUser.GetUser(userId);
if (foundUser == null) {
ViewData["ErrorMessage"] = "Could not find user with ID {0}.".FormatWith(userId);
return View("UsersRegister");
}
Конечно, как только вы перемещаете в классе обслуживания, вы потеряете прямой доступ к ViewData
, TempData
и методы, подобные View()
или RedirectToAction()
, поэтому я пытаюсь найти оптимальную практику для решения этой проблемы. Два решения приходят на ум:
Создайте класс, содержащий различные части информации о том, что контроллер должен делать, чтобы быть переданы обратно от услуг, как:
public class ResponseInfo { public string Name { get; set; } public bool DoRedirect { get; set; } public object RedirectRouteValues { get; set; } public string InfoMessage { get; set; } public string ErrorMessage { get; set; } }
Try и позволяют методы обслуживания, чтобы иметь прямой доступ к вещам, как
ViewData
иTempData
, например .:public ActionResult ToggleUserAttended(int eventId, int userId, HttpRequestBase request, TempDataDictionary tempData, ViewDataDictionary viewData, Func<string, object, ActionResult> redirectAction) { //... var repoUser = new UserRepository(); var foundUser = repoUser.GetUser(userId); if (foundUser == null) { tempData["ErrorMessage"] = "Could not find user with ID {0}.".FormatWith(userId); return redirectAction("UsersRegister", new { id = eventId, returnUrl = request.QueryString["returnUrl"] }); } //... }
..., а затем в контроллере:
return _svcEvent.ToggleUserAttended(123, 234, Request, TempData, ViewData, (name, routeVals) => RedirectToAction(name, routeVals));
Для числа 1, контроллер будет иметь больше логики, чтобы сделать в глядя на ResponseInfo
объекта и определения того, чтобы перенаправить, отображать вид, подключив ошибки или информационные сообщения в TempData
или ViewData
, и т.д. Число 2 в значительной степени позволит использовать однострочный контроллер, но вы делаете сервис очень осведомленным о специфике контроллера. Однако служба всегда будет тесно связана с контроллером, так что это проблема? Будет ли 1 или 2 быть лучшей практикой или что-то еще, что я не перечислял?
БОГ НЕТ. Переместите что-то в «ActionFilter's ... Просто не делайте этого, пожалуйста, не позволяйте вашим службам обращаться к интерфейсным концепциям, таким как« ViewData »и« TempData ». –
@SimonWhitehead Итак, вы в основном говорите: оставить этот материал в контроллере? Как насчет сообщений об ошибках? Более полный ответ был бы оценен. – Jez
Есть ли причина, по которой вы не рассматривали использование модели ModelState для отображения этих ошибок? Вы можете иметь карту уровня пользовательского интерфейса между списками ошибок уровня сервиса и «ModelStateDictionary». Это отменит вашу службу от вашего пользовательского интерфейса. Вы даже можете написать свой собственный «ActionResult», чтобы он полностью его отобразил и значительно уменьшил ваши действия. Я сейчас не рядом с ПК, чтобы напечатать пример. –