2016-03-09 2 views
6

Шаблон контроллера WebAPI в MVC6/WebAPI реализует действие, которое возвращает коллекцию для метода Получить как это:Возвращение строки ошибки из MVC6 контроллера/WepApi

[HttpGet] 
public IEnumerable<MyEntity> Get() 
{ 
    //my code to return entities 
} 

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

Насколько я заметил, исключение приведет к HTTP 500. Это нормально, но я хотел бы дать вызывающему сообщение сообщение о том, что пошло не так. Из-за подписи действия шаблона я не могу поймать исключение и возвратить экземпляр Http *** или ObjectResult.

+0

Посмотрите ответы на [эту] (http://stackoverflow.com/q/31054012/5233410) Вопрос – Nkosi

ответ

10

Вам нужно будет добавить код, который будет обрабатывать ошибки и возвращать сообщение.

Один из вариантов - использовать фильтр исключений и добавить его либо глобально, либо выбранные контроллеры, хотя этот подход будет охватывать исключения, исходящие из методов действий контроллера. Например, следующий фильтр будет возвращать объект JSON только тогда, когда запрос принимает было применение/JSON (В противном случае это позволило бы исключению пройти через которые, например, могут быть обработаны с помощью глобальной страницы ошибок):

public class CustomJSONExceptionFilter : ExceptionFilterAttribute 
{  
    public override void OnException(ExceptionContext context) 
    { 
     if (context.HttpContext.Request.GetTypedHeaders().Accept.Any(header => header.MediaType == "application/json")) 
     { 
      var jsonResult = new JsonResult(new { error = context.Exception.Message }); 
      jsonResult.StatusCode = Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError; 
      context.Result = jsonResult; 
     } 
    } 
} 

services.AddMvc(opts => 
{ 
    //Here it is being added globally. 
    //Could be used as attribute on selected controllers instead 
    opts.Filters.Add(new CustomJSONExceptionFilter()); 
}); 

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

public IActionResult Get() { 
    try { 
     IEnumerable<MyEntity> result; 
     //...result populated 
     return new HttpOkObjectResult(result); 
    } catch (Exception ex) { 
     //You should handle the error 
     HandleError(ex);//the is not an actual method. Create your own. 
     //You could then create your own error so as not to leak 
     //internal information. 
     var error = new 
      { 
       message = "Enter you user friendly error message", 
       status = Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError 
      }; 
     Context.Response.StatusCode = error.status;    
     return new ObjectResult(error); 
    } 
} 
+1

Вместе со ссылкой, которую вы предоставили, что делает три возможных способа сделать это. Я посмотрю, что лучше подходит. Я приму свой ответ! – NicolasR

1

Как и для любой программы.

try { 
    ... 
} catch (Exception e) { 
    return errorMessageView; 
} 

В качестве альтернативы вы можете использовать HandleErrorAttribute.

+0

Спасибо, но я думаю, что я не был» t достаточно ясно. Я пишу API, поэтому я не хочу возвращать представление. Клиент должен проверить Http OK (200) или 500 (внутренняя ошибка). Если клиент получил 500, он должен иметь возможность отображать сообщение об ошибке. Как получить это сообщение об ошибке от обработчика исключений к клиенту? Поиск HandleErrorAttribute Я нашел HttpResponseException, но это, похоже, не поддерживается в MVC 6. – NicolasR

+0

вы можете вернуть JSON '{'result': 'error', 'status', 500}'? – will

+0

Только когда я меняю оператор return, но это выглядит неестественно, потому что шаблон контроллера всегда создает действия Get с возвращающимися коллекциями. Из того, что другие предложили, похоже, что лучший способ - разрешить исключение и внедрить промежуточное программное обеспечение фильтра или ошибки. – NicolasR

3

Изменить способ выглядеть

[HttpGet] 
[ResponseType(typeof(IEnumerable<MyEntity>))] 
public IHttpActionResult Get() 
{ 
    //when ok 
    return Ok(response); // response is your IEnumerable<MyEntity> 

    //when error 
    throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.WhateverStatusCodeSuitable) 
      { 
       ReasonPhrase = "your message" 
      }); 

} 
+2

Выглядит неплохо, но как объясняется в этом сообщении http://stackoverflow.com/questions/31054012/asp-net-5-mvc-6-equivalent-of-httpexception?lq=1 HttpResponseException больше не доступно. – NicolasR

0

Вы можете бездельничать с исключениями, но я получаю впечатление, что мы не должны думать, как что-либо другое. Это, как представляется, Дзен MVC6:

[HttpGet("{id}")] 
    [ProducesResponseType(typeof(IEnumerable<string>), 200)] 
    [ProducesResponseType(typeof(void), 404)] 
    public IActionResult Get(int id) 
    { 
     Product product = null; 
     if (!this.productRepository.TryGet(id, out product)) 
     { 
      return NotFound(); 
     } 

     return Ok(product); 
    } 
+0

Если бы это было только о найденном или не найденном, то хорошо.Но как насчет всех фактических исключений, которые происходят в реалистичных сценариях, таких как сломанная база данных, недоступные вложенные службы и, а не забыть, ошибки, введенные программистами. Я согласен с тем, что IActionResult предоставил бы мне свободу возвращать все необходимое, но это означало бы, что я должен был перехватывать исключения в каждом методе контроллера, чтобы преобразовать его в нечто вроде «Произошла ошибка, проконсультируйтесь ...» (как минимум). – NicolasR

+0

Хотелось бы вам это или нет, все эти исключения превращаются в HTTP-результаты той или иной формы. Это, ИМО, просто захватывает эту парадигму, а не дает иллюзию, что какое-то исключение фактически передается клиенту. –

+0

Я согласен с вами в отношении парадигмы, и я использую код, как вы опубликовали в большинстве моих методов. С другой стороны, посмотрите на второй фрагмент кода в ответе Nkosi. Я действительно не хочу иметь такой код в каждом из моих контроллеров. Моя проблема заключается в том, что обработчик исключений по умолчанию возвращает код 500 только клиенту без текста ошибки. Вот почему мне нравится решение CustomExceptionFilter. – NicolasR

Смежные вопросы