Как использовать HandleError с ошибками состояния модели - PullRequest
3 голосов
/ 28 марта 2011

Я хочу использовать фильтр настраиваемых действий для обработки определенных исключений из моих классов обслуживания, чтобы заполнить состояние модели и затем вернуть представление.

Например, возьмите мой предыдущий код:

public ActionResult SomeAction(SomeViewModel model)
{
    try
    {
        _someService.SomeMethod(model);
    }
    catch (ServiceException ex)
    {
        ModelState.AddModelError(ex.Key, ex.ErrorMessage);
    }

    return View();
}

По сути, он будет вызывать службу, и если возникнет исключение ServiceException, он узнает, что существует проблема с данными модели, и добавит ошибку в ModelState, а затем просто вернет представление. Но я заметил некоторые очень не похожие на DRY шаблоны, потому что у меня был один и тот же код try / catch в каждом методе действия.

Итак, чтобы немного подсушить, я в основном создал новый фильтр действий HandleServiceError:

public class HandleServiceErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        ((Controller)context.Controller)
            .ModelState
            .AddModelError(
                ((ServiceException)context.Exception).Key, 
                ((ServiceException)context.Exception).ErrorMessage
            );
        context.ExceptionHandled = true;
    }
}

Затем упростили мои методы действий так:

public ActionResult SomeAction(SomeViewModel model)
{
    _someService.SomeMethod(model);
    return View();
}

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

Возможно ли это?

Заранее спасибо.

UPDATE:

Я попробовал предложения из статьи , которые Дарин предоставил в своем ответе, но столкнулся с проблемами, пытаясь использовать инжекцию конструктора с состоянием модели контроллера.

Например, если вы посмотрите на их код Controllers \ ProductController.cs, у них есть пустой конструктор контроллера, использующий локатор службы для создания службы, передавая ModelState контроллера в этот момент:

public ProductController() 
{
    _service = new ProductService(new ModelStateWrapper(this.ModelState), 
                                  new ProductRepository());
}

Но если вы посмотрите на внедренный конструктор, он предполагает, что ModelState будет внедрен в конструктор для службы:

public ProductController(IProductService service)
{
    _service = service;
}

Я не знаю, как заставить CI работать с ModelState текущего контроллера. Если бы я мог понять это, то этот подход может сработать.

1 Ответ

0 голосов
/ 28 марта 2011

Вы все еще можете вернуть соответствующее представление:

context.Result = new ViewResult
{
    ViewName = context.RouteData.GetRequiredString("action")
};

Вы также можете взглянуть на следующую статью для альтернативы о том, как выполнить проверку на уровне службы.

...