Возврат исключений в виде сообщений JSON

Я занимаюсь разработкой API с ASP.NET Core и борюсь с обработкой исключений.

Когда возникает какое-либо исключение или в любом контроллере, где я хочу вернуть пользовательские ошибки с разными кодами состояния, я хочу вернуть отчеты об исключениях в формате JSON. Мне не нужен HTML в ответах об ошибках.

Я не уверен, стоит ли мне использовать промежуточное программное обеспечение для этого или что-то еще. Как я должен возвращать исключения JSON в ASP.NET Core API?

 Set01 авг. 2016 г., 12:35
 Hinrich29 июл. 2016 г., 19:35
Извините, написал вопрос во время тренировки. Подробно расскажу об этом, когда вернусь в офис.
 Dawid Ferenczy Rogožan29 июл. 2016 г., 19:24
Извините, но "не работает" - это чепуха. ПроверитьКак создать минимальный, полный и проверяемый пример, пожалуйста.
 Nate Barbettini29 июл. 2016 г., 19:52
@ Генрих Я думал, что у вопроса есть потенциал для хорошего канонического ответа, поэтому я позволил себе немного отредактировать и предложить решение. Не стесняйтесь откатываться или редактировать дальше, если вы чувствуете, что я слишком сильно изменил значение вашего вопроса.

Ответы на вопрос(2)

Фильтр исключений (как атрибут или глобальный фильтр) - это то, что вы ищете. Отдокументы:

Фильтры исключений обрабатывают необработанные исключения, в том числе те, которые возникают во время создания контроллера и привязки модели. Они вызываются только тогда, когда в конвейере возникает исключение. Они могут предоставить единое местоположение для реализации общих политик обработки ошибок в приложении.

Если ты хочешьлюбой необработанное исключение, которое будет возвращено как JSON, это самый простой метод:

public class JsonExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        var result = new ObjectResult(new
        {
            code = 500,
            message = "A server error occurred.",
            detailedMessage = context.Exception.Message
        });

        result.StatusCode = 500;
        context.Result = result;
    }
}

Вы можете настроить ответ, чтобы добавить столько деталей, сколько вы хотите. ObjectResult будет сериализован в JSON.

Добавьте фильтр как глобальный фильтр для MVC при запуске:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(JsonExceptionFilter));
    });
}
 Hinrich31 июл. 2016 г., 13:47
Это обрабатывает все мои неосознанные сбои, что является хорошим началом. Спасибо. Но что, если я хочу вернутьBadRequest или любой другой код состояния из контроллера программно?
 Set01 авг. 2016 г., 12:44
обратите внимание, что фильтры исключений обрабатывают только исключения MVC, более общий подход в ASP.NET Core заключается в использовании промежуточного программного обеспечения ExceptionHandler:stackoverflow.com/documentation/asp.net-core/1479/middleware/...
Решение Вопроса

Хорошо, у меня есть рабочее решение, которым я очень доволен.

добавлятьпромежуточный слой: ВConfigure Метод, зарегистрируйте промежуточное программное обеспечение (поставляется с ASP.NET Core).

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // logging stuff, etc.

    app.UseStatusCodePagesWithReExecute("/error/{0}");
    app.UseExceptionHandler("/error");

    app.UseMvc(); // if you are using Mvc

    // probably other middleware stuff 
}

Создайте класс для сообщений. Напишите простой класс, который представляет экземплярыСообщения об ошибках JSON Вы хотите отправить запрос в случае ошибки:

public class ExceptionMessageContent
{

    public string Error { get; set; }
    public string Message { get; set; }

}

Создать контроллер ошибок добавитьКонтроллер ошибок это обрабатывает все ожидаемые и неожиданные ошибки. Обратите внимание, что эти маршруты соответствуют конфигурации промежуточного программного обеспечения.

[Route("[controller]")]
public class ErrorController : Controller
{

    [HttpGet]
    [Route("")]
    public IActionResult ServerError()
    {

        var feature = this.HttpContext.Features.Get<IExceptionHandlerFeature>();
        var content = new ExceptionMessageContent()
        {
            Error = "Unexpected Server Error",
            Message = feature?.Error.Message
        };
        return Content( JsonConvert.SerializeObject( content ), "application/json" );

    }


    [HttpGet]
    [Route("{statusCode}")]
    public IActionResult StatusCodeError(int statusCode)
    {

        var feature = this.HttpContext.Features.Get<IExceptionHandlerFeature>();
        var content = new ExceptionMessageContent() { Error = "Server Error", Message = $"The Server responded with status code {statusCode}" };
        return Content( JsonConvert.SerializeObject( content ), "application/json" );

    }
}

Теперь, когда я хочу выдать ошибку в любом месте, я могу просто сделать это. Запрос перенаправляется в обработчик ошибок и отправляет500 с хорошим отформатированным сообщением об ошибке. Также,404 и другие коды обрабатываются изящно. Любые пользовательские коды состояния, которые я хочу отправить, я также могу вернуть их с экземпляром моегоExceptionMessageContent, например:

// inside controller, returning IActionResult

var content = new ExceptionMessageContent() { 
    Error = "Bad Request", 
    Message = "Details of why this request is bad." 
};

return BadRequest( content );

Ваш ответ на вопрос