OK以外の応答に対してIHttpActionResultでコンテンツを返す


185

Web API 2コントローラーから戻る場合、次のように応答がOK(ステータス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);
    }

またはより良い方法はありますか?




@Milen、ありがとう。そのような何かがうまくいくかもしれません。私が好きではない部分は、使用できるようにする既存の実装ごとに異なるIHttpActionResult実装を作成する必要があることです。
mayabelle 2015

@Ric、いいえ、パラメーターは例外です。メッセージを文字列として設定したい。また、これは、コードが必ずしもサーバーの内部エラーであるとは限らない、より一般的なケースには対応していません。
Mayabelle 2015

3
@mayabelle:シャミル・ヤクポフの答えを見ましたか?受け入れられた答えの方がはるかに単純で簡潔です。
アイザック

回答:


420

あなたはこれを使うことができます:

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

1
短くてシンプルなソリューション。コードが増えると、バグが増え、メンテナンスに時間がかかります。
Thomas.Benz

6
これを試してみると、code(コードは文字列です)in の戻り値がreturn Content(HttpStatusCode.OK, code)"にカプセル化されます。これは予期しないことです。理由はありますか?たとえば、返される値は"\"value\""mvc5を使用しています
Deza

2
ApiControllerクラスの外側からこれを行う必要がある場合は、次を使用できます。return new NegotiatedContentResult <T>(code、new T(...)、controller)
Etherman

クラスライブラリから返すことはできますか?何を参照する必要がありますか?
ツールキット

54

次のように、HttpRequestMessagesExtensions.CreateErrorResponseSystem.Net.Http名前空間)を使用できます。

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

Web APIのコンテンツネゴシエーションを利用するには、要求に基づいて応答を作成することが推奨されます。


6
Request.CreateErrorResponseは、IHttpActionResultではなく、HttpResponseMessageを返します。あなたが説明するのはHttpResponseMessageを作成するための良い習慣ですが、私の質問には対応していません。とにかくありがとう!
Mayabelle 2015

@mayabelleあなたはIHttpActionResultコンクリートを作成し、このようなものをコードラップすることができます
コックグエン

1
これは私にとってはうまくいきましたが、Request.CreateResponseを使用して、エラーがメッセージキーの下ではなく文字列として表示されるようにしました。
化学者2017

エラーが発生し、スニペットが失敗します。「リクエスト」はnullと表示されています。私はRequest.CreateResponse @ user1620220使用しようとしています
シーナアグラワル

@SheenaAgrawalこのコードは、HTTPリクエストのコンテキストでのみ実行できます。ApiController.Requestがnullの場合は、適切なコンテキストにないか、WebAPIアーキテクチャで何かが壊れていることを意味します。
user1620220

35

私は次の解決策に行き着きました:

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
}

私は改善のための提案を受け入れています。:)


1
シャミルヤクポフの答えは最良の答えですが、ApiControllerクラスの内部からのみです。外部から使用するには、「return new NegotiatedContentResult <T>(code、new T(...)、controller)」のように書き直す必要があります。コントローラクラス。その場合、上記のようなソリューションは、より読みやすくなる可能性があります。
Etherman、2017

16

あなたも行うことができます:

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

1
はい、でもそのメッセージテキストを取り戻すのは
大変

7

ResponseMessageを返すことで、ステータスコードのあるものを返すことに興味がある人:

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

7

ASP.NET Web API 2では、任意のものResponseMessageResponseMessageResultでラップできます。

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

場合によっては、これが目的の結果を得るための最も簡単な方法である可能性がありますが、通常はSystem.Web.Http.Resultsのさまざまな結果を使用する方が望ましい場合があります。


6

シンプル:

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

System.Net.HttpおよびSystem.Netを参照することを忘れないでください。



2

C#で定義されていないHTTPコードをサポートするより詳細な例HttpStatusCode

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

ContentApiControllerコントローラのベースである抽象クラスで定義された仮想メソッドです。以下の宣言を参照してください。

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

1

@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;
    }
}

0

私も同じ問題を抱えていました。APIコントローラーのカスタム結果を作成して、次のように呼び出します return Ok("some text");

それから私はこれをしました:1)シングルトーンでカスタム結果タイプを作成します

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();
    }

0

この回答は、文字列ではなく実際のオブジェクトを使用したシャミルヤクポフの回答に基づいています。

using System.Dynamic;

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

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

1
Content <T>は非常に便利です
LastTribunal 2018

0

例外として、私は通常

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

0

上記のものは本当に役に立ちます。

Webサービスを作成しながら、サービスのケースを取るなら消費者は大歓迎です。出力の均一性を維持しようとしました。また、備考や実際のエラーメッセージを表示することもできます。Webサービスのコンシューマーは、IsSuccessがtrueであるかどうかを確認することしかできません。

  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 )); 
            } 
        }

あれば提案を歓迎します:)


-1

答えが遅くなってすみません

return BadRequest("your message");

私はすべてのIHttpActionResultエラーにそれを使用しています

ここにドキュメントがあります:https : //msdn.microsoft.com/en-us/library/system.web.http.apicontroller.badrequest(v=vs.118).aspx


7
すべてのエラーが悪い要求の結果であるとは限らないため、400応答は不適切です。OPは500、例として具体的に応答を示しました。
user1620220

はい、それはBadRequestでのみ可能です。他のタイプはメッセージ引数を取らない
benraay
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.