Редактирование обслуживания
После некоторого использования этого подхода я обнаружил, что добавляю только один и тот же код шаблона в каждом контроллере, поэтому решил сделать магию отражения. Тем временем я бросил с использованием MVC для своих просмотров - Razor просто так скучен и уродлив, поэтому я в основном использую мои обработчики как бэкэнд JSON. Подход, который я использую в настоящее время, заключается в том, чтобы украсить мои запросы/команды атрибутом Route
, который находится в некоторой общей сборке, например:
[Route("items/add", RouteMethod.Post)]
public class AddItemCommand { public Guid Id { get; set; } }
[Route("items", RouteMethod.Get)]
public class GetItemsQuery : IQuery<GetItemsResponse> { }
// The response inherits from a base type that handles
// validation messages and the like
public class GetItemsResponse : ServiceResponse { }
Затем я реализовал хост MVC, который извлекает аннотированные команды/запросы и генерирует контроллеры и обработчики для меня во время запуска. Таким образом, моя логика приложения, наконец, свободна от MVC cruft. Ответы на запросы также автоматически заполняются сообщениями проверки. Мои приложения MVC теперь выглядят следующим образом:
+ MvcApp +- Global.asax +- Global.asax.cs - Startup the host and done +- Web.config
Поняв, что я действительно не использую MVC за пределами хоста, и постоянно испытываю проблемы с зависимостями bazillion, которые имеют инфраструктура, я реализовал другой хост на основе NServiceKit. Ничто не должно меняться в моей логике приложения, а зависимости ниже System.Web
, NServiceKit
и NServiceKit.Text
, которые хорошо заботятся о привязке модели. Я знаю, что это очень похожий подход к тому, как NServiceKit/ServiceStack
делает свои вещи, но теперь я полностью отключаюсь от используемой веб-фреймворки, поэтому, если будет лучше, я просто реализую другой хост и что он.
Ситуация
В настоящее время я работаю над сайтом ASP.NET MVC, который реализует разделение бизнес-вида через IQueryHandler и ICommandHandler абстракции (используя всемогущий SimpleInjector для инъекции зависимостей).
Проблема
Мне нужно приложить некоторую пользовательскую логику проверки к QueryHandler
через декоратор и работать очень хорошо само по себе. Проблема в том, что в случае ошибок проверки я хочу иметь возможность показать тот же вид, что действие вернулось бы, но с информацией об ошибке проверки, конечно. Вот пример для моего случая:
public class HomeController : Controller
{
private readonly IQueryHandler<SomeQuery, SomeTransport> queryHandler;
public ActionResult Index()
{
try
{
var dto = this.queryHandler.Handle(new SomeQuery { /* ... */ });
// Doing something awesome with the data ...
return this.View(new HomeViewModel());
}
catch (ValidationException exception)
{
this.ModelState.AddModelErrors(exception);
return this.View(new HomeViewModel());
}
}
}
В этом случае у меня есть некоторая бизнес-логика, обрабатываемая QueryHandler
, которая украшена ValidationQueryHandlerDecorator
, которая бросает ValidationException
, когда это уместно.
Что я хочу делать
Я хочу что-то вроде:
public class HomeController : Controller
{
private readonly IQueryHandler<SomeQuery, SomeTransport> queryHandler;
public ActionResult Index()
{
var dto = this.queryHandler.Handle(new SomeQuery { /* ... */ });
// Doing something awesome with the data ...
// There is a catch-all in place for unexpected exceptions but
// for ValidationExceptions I want to do essentially the same
// view instantiation but with the model errors attached
return this.View(new HomeViewModel());
}
}
Я думал о специальном ValidationErrorHandlerAttribute
, но потом я теряю контекст, и я не могу действительно вернуть правильный вид. То же самое касается подхода, в котором я просто обертываю IQueryHandler<,>
декоратором... Я видел некоторые странные фрагменты кода, которые выполняли некоторую струйку на маршруте, а затем создавали экземпляр нового контроллера и viewmodel через Activator.CreateInstance
- это не кажется хорошей идеей.
Так что мне интересно, есть ли хороший способ сделать это... может быть, я просто не вижу дерева с деревьев. Спасибо!