Лучшая практика: способы обработки ошибок и исключений в контроллерах web-api?
Я работаю над проектом и в значительной степени полагаюсь на веб-api для всех своих операций на стороне клиента, будь то обновление учетной записи, новые детали, изменение, все было сделано с помощью ASP.NET Web Api и Backbone.js
Текущая сцена:
В текущей схеме вещей я возвращаю логическое значение из своих веб-контроллеров api, чтобы указать, была ли операция успешной или нет.
Пример:
[ActionName("UpdateAccountDetails")]
public bool PostAccountDetails(SomeModel model)
{
bool updateStatus = _customService.UpdateAccountDetails(model);
return updateStatus;
}
поэтому после выполнения ajax-вызова этого действия я проверяю ответ на истинные/ложные и выводит сообщение об ошибке или сообщения об успешном завершении.
Проблема:
Теперь случилось то, что я начал получать исключения в своем действии, и действие продолжало возвращать false, и было показано сообщение об ошибке. Но я не смог найти почему?
Итак, мне было интересно, существует ли стандартная структура ответа api, которую каждый из них следует?
Я изначально придумал эту идею, чтобы каждое действие веб-api возвращало этот класс
public class OperationStatus
{
public bool Result { get; set; } // true/false
public string Status { get; set; } // success/failure/warning
public List<string> WarningMessages { get; set; }
public List<string> ErrorMessages { get; set; }
public string OtherDetails { get; set; }
}
Это изменение будет серьезным изменением, и это будет время и ресурсы, поэтому я подумал, что лучше иметь второе/третье/четвертое мнение по этому поводу.
Подумайте об этом.
Обновление:
С помощью небольшой помощи от Mark Jones я придумал этот
[ActionName("UpdateAccountDetails")]
public HttpResponseMessage PostAccountDetails(SomeModel model)
{
bool updateStatus;
string errorMessage;
try{
updateStatus = _customService.UpdateAccountDetails(model);
if(updateStatus)
{
return Request.CreateResponse(HttpStatusCode.OK);
}
return Request.CreateResponse(HttpStatusCode.InternalServerError);
}
catch(Exception exception)
{
errorMessage = exception.Message;
return Request.CreateResponse(HttpStatusCode.InternalServerError, errorMessage);
}
return updateStatus;
}
Любая мысль об этом?
Ответы
Ответ 1
Вам следует избегать использования try/catch в действии контроллера.
Существует множество способов решения вашей проблемы.
Простейшим и самым чистым решением, вероятно, будет использование ActionFilter
для обработки исключений, что-то вроде строк:
public class ExceptionAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
Debug.WriteLine(context.Exception);
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("An error occurred!"),
ReasonPhrase = "Deadly Exception"
});
}
}
Затем вы можете просто украсить свое действие [ExceptionAttribute]
.
Разумеется, вы можете расширить это поведение по-разному для разных типов исключений - бизнес-исключения, исключения данных, исключения IO и т.д., А также вернуть другие коды состояния и обратную связь на основе этого.
Я рекомендую вам прочитать отличную статью Фредрика Нормена - "Обработка исключений веб-API ASP.NET" http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx.
Он предоставляет большой обзор методов обработки исключений для веб-API.
Ответ 2
Вместо того, чтобы возвращать HttpResponseMessage, я бы оставил API одинаковым и просто выбросил исключение HttpResponseException, когда вы поймаете исключение. Что-то вроде этого:
throw new HttpResponseException(
new HttpResponseMessage(HttpStatusCode.InternalServerError)
{ ReasonPhrase = errorMessage });
Таким образом, вы не изменяете определение своего API и не будете работать с вашими действиями GET, где вы возвращаете некоторый объект, который должен быть сериализован. Если вы используете JQuery ajax-метод для отправки запроса, ваш обработчик error поймает это, и вы сможете получить текстовое сообщение в параметре errorThrown и обработать его соответствующим образом.