Возвращать содержимое с помощью IHttpActionResult для ответа без ответа

Для возврата из контроллера Web API 2 я могу вернуть контент с ответом, если ответ в порядке (состояние 200) выглядит следующим образом:

    public IHttpActionResult Get()
    {
        string myResult = ...
        return Ok(myResult);
    }

Если возможно, я хочу, когда это возможно, использовать встроенные типы результатов: https://msdn.microsoft.com/en-us/library/system.web.http.results(v=vs.118).aspx

Мой вопрос в том, что для другого типа ответа (не 200), как я могу вернуть ему сообщение (строку)? Например, я могу это сделать:

    public IHttpActionResult Get()
    {
       return InternalServerError();
    }

но не это:

    public IHttpActionResult Get()
    {
       return InternalServerError("Message describing the error here");
    }

В идеале я хочу, чтобы это было обобщено, чтобы я мог отправить сообщение обратно с любой из реализаций IHttpActionResult.

Мне нужно сделать это (и создать собственное ответное сообщение):

    public IHttpActionResult Get()
    {
       HttpResponseMessage responseMessage = ...
       return ResponseMessage(responseMessage);
    }

или есть лучший способ?

Ответ 1

В итоге я решил использовать следующее решение:

public class HttpActionResult : IHttpActionResult
{
    private readonly string _message;
    private readonly HttpStatusCode _statusCode;

    public HttpActionResult(HttpStatusCode statusCode, string message)
    {
        _statusCode = statusCode;
        _message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = new HttpResponseMessage(_statusCode)
        {
            Content = new StringContent(_message)
        };
        return Task.FromResult(response);
    }
}

... который можно использовать следующим образом:

public IHttpActionResult Get()
{
   return new HttpActionResult(HttpStatusCode.InternalServerError, "error message"); // can use any HTTP status code
}

Я открыт для предложений по улучшению.:)

Ответ 2

Вы можете использовать это:

return Content(HttpStatusCode.BadRequest, "Any object");

Ответ 3

Вы можете использовать HttpRequestMessagesExtensions.CreateErrorResponse (System.Net.Http namespace), например:

public IHttpActionResult Get()
{
   return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Message describing the error here"));
}

Предпочтительно создавать ответы на основе запроса, чтобы использовать преимущества согласования содержимого веб-API.

Ответ 4

Вы также можете сделать:

return InternalServerError(new Exception("SOME CUSTOM MESSAGE"));

Ответ 5

Любой, кто заинтересован в возвращении чего-либо с любым кодом состояния с возвратом ResponseMessage:

//CreateResponse(HttpStatusCode, T value)
return ResponseMessage(Request.CreateResponse(HttpStatusCode.XX, object));

Ответ 6

В ASP.NET Web API 2 вы можете заключить любое ResponseMessage в ResponseMessageResult:

public IHttpActionResult Get()
{
   HttpResponseMessage responseMessage = ...
   return new ResponseMessageResult(responseMessage);
}

В некоторых случаях это может быть самый простой способ получить желаемый результат, хотя обычно может быть предпочтительнее использовать различные результаты в System.Web.Http.Results.

Ответ 7

Просто:

return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Your message"));

Не забудьте сослаться на System.Net.Http и System.Net.

Ответ 8

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

Например, если я писал службу WCF, я мог бы следовать этот учебник, чтобы напрямую возвращать сообщение об исключении как часть ответа статус:

Ошибка

В большинстве ответов здесь также возвращается статус 500, но сообщение об ошибке возвращается как объект JSON или отдельная строка ответа, а не является частью статуса ответа.

Например, если бы я использовал этот код:

catch (Exception ex)
{
    return new System.Web.Http.Results.ResponseMessageResult(
        Request.CreateErrorResponse((HttpStatusCode)500, 
            new HttpError("Something went wrong")));
}

... затем он возвращает общее сообщение 500, и исключение возвращается в строке JSON.

введите описание изображения здесь

Я нахожу намного более аккуратным, чтобы текст текста исключения был как часть StatusDescription. Есть ли способ сделать это, в контроллере Web API 2, который возвращает IHttpActionResult?

Ответ 9

Я бы порекомендовал прочитать этот пост. Существует множество способов использовать существующий HttpResponse, как это было предложено, но если вы хотите воспользоваться Web Api 2, посмотрите на использование некоторых встроенных опций IHttpActionResult, таких как

return Ok() 

или же

return NotFound()

Выберите правильный тип возврата для контроллеров Web Api

Ответ 10

@mayabelle вы можете создать бетон IHttpActionResult и обернуть этот код следующим образом:

public class NotFoundPlainTextActionResult : IHttpActionResult
{
    public NotFoundPlainTextActionResult(HttpRequestMessage request, string message)
    {
        Request = request;
        Message = message;
    }

    public string Message { get; private set; }
    public HttpRequestMessage Request { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(ExecuteResult());
    }

    public HttpResponseMessage ExecuteResult()
    {
        var response = new HttpResponseMessage();

        if (!string.IsNullOrWhiteSpace(Message))
            //response.Content = new StringContent(Message);
            response = Request.CreateErrorResponse(HttpStatusCode.NotFound, new Exception(Message));

        response.RequestMessage = Request;
        return response;
    }
}

Ответ 11

У меня была та же проблема. Я хочу создать пользовательский результат для своих api-контроллеров, чтобы вызвать их как return Ok("some text");

Тогда я сделал следующее: 1) Создайте собственный тип результата с помощью singleletone

public sealed class EmptyResult : IHttpActionResult
{
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.NoContent) { Content = new StringContent("Empty result") });
    }
}

2) Создайте настраиваемый контроллер с помощью нового метода:

public class CustomApiController : ApiController
{
    public IHttpActionResult EmptyResult()
    {
        return new EmptyResult();
    }
}

И затем я могу вызвать их в своих контроллерах, например:

public IHttpActionResult SomeMethod()
    {
       return EmptyResult();
    }

Ответ 12

этот ответ основан на ответе Шамиля Якупова, с реальным объектом вместо строки.

using System.Dynamic;

dynamic response = new ExpandoObject();
response.message = "Email address already exist";

return Content<object>(HttpStatusCode.BadRequest, response);

Ответ 13

За исключением, я обычно делаю

 catch (Exception ex)
        {
            return InternalServerError(new ApplicationException("Something went wrong in this request. internal exception: " + ex.Message));
        }

Ответ 14

Выше вещи действительно полезны.

При создании веб-сервисов, если вы воспользуетесь услугами, потребитель будет очень благодарен. Я пытался поддерживать единообразие вывода. Также вы можете дать замечание или актуальное сообщение об ошибке. Потребитель веб-службы может только проверить, верно ли IsSuccess или нет, иначе он будет уверен в наличии проблемы и будет действовать в соответствии с ситуацией.

  public class Response
    {
        /// <summary>
        /// Gets or sets a value indicating whether this instance is success.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is success; otherwise, <c>false</c>.
        /// </value>
        public bool IsSuccess { get; set; } = false;

        /// <summary>
        /// Actual response if succeed 
        /// </summary>
        /// <value>
        /// Actual response if succeed 
        /// </value>
        public object Data { get; set; } = null;

        /// <summary>
        /// Remark if anythig to convey
        /// </summary>
        /// <value>
        /// Remark if anythig to convey
        /// </value>
        public string Remark { get; set; } = string.Empty;
        /// <summary>
        /// Gets or sets the error message.
        /// </summary>
        /// <value>
        /// The error message.
        /// </value>
        public object ErrorMessage { get; set; } = null;


    }  




[HttpGet]
        public IHttpActionResult Employees()
        {
            Response _res = new Response();
            try
            { 
                DalTest objDal = new DalTest(); 
                _res.Data = objDal.GetTestData();
                _res.IsSuccess = true;
                return Ok<Response>(_res);
            }
            catch (Exception ex)
            {
                _res.IsSuccess = false;
                _res.ErrorMessage = ex;
                return ResponseMessage(Request.CreateResponse(HttpStatusCode.InternalServerError, _res )); 
            } 
        }

Вы можете дать предложение, если таковые имеются :)

Ответ 15

Для .NET Core вы можете использовать: return new StatusCodeResult(500);

Ответ 16

Более подробный пример с поддержкой HTTP-кода, не определенного в С# HttpStatusCode.

public class MyController : ApiController
{
    public IHttpActionResult Get()
    {
        HttpStatusCode codeNotDefined = (HttpStatusCode)429;
        return Content(codeNotDefined, "message to be sent in response body");
    }
}

Content - это виртуальный метод, определенный в абстрактном классе ApiController, базе контроллера. См. объявление ниже:

protected internal virtual NegotiatedContentResult<T> Content<T>(HttpStatusCode statusCode, T value);