web-dev-qa-db-ja.com

新しいIHttpActionResultアクション結果メソッドの作成

新しいIHttpActionResultインターフェイスを使用して_HttpStatusCode.NoContent_応答メッセージを返す方法はありますか?

現在return new HttpResponseMessage( HttpStatusCode.NoContent );を使用していますが、これをreturn NoContent();に変換したいと思います。

IHttpActionResultはすでにOk()Conflict()、およびNotFound()を取得していますが、Forbidden()およびNoContent()プロジェクトで使用する必要があります。

他の結果タイプを追加するのは簡単ですか?

36
Intrepid

これを見つけました サンプルサイト カスタムIHttpActionResultメソッドを追加する方法を示し、これを使用してForbidden()およびNoContent()を作成しました大成功を収めた方法。

public abstract class CommonApiController : ApiController
{
    public class ForbiddenResult : IHttpActionResult
    {
        private readonly HttpRequestMessage _request;
        private readonly string _reason;

        public ForbiddenResult(HttpRequestMessage request,string reason)
        {
            _request = request;
            _reason = reason;
        }

        public ForbiddenResult(HttpRequestMessage request)
        {
            _request = request;
            _reason = "Forbidden";
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = _request.CreateResponse(HttpStatusCode.Forbidden,_reason);
            return Task.FromResult(response);
        }
    }

    public class NoContentResult : IHttpActionResult
    {
        private readonly HttpRequestMessage _request;
        private readonly string _reason;

        public NoContentResult(HttpRequestMessage request,string reason)
        {
            _request = request;
            _reason = reason;
        }

        public NoContentResult(HttpRequestMessage request)
        {
            _request = request;
            _reason = "No Content";
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = _request.CreateResponse(HttpStatusCode.NoContent,_reason);
            return Task.FromResult(response);
        }
    }
}

そして、私はこれを次のように使用できます:

public class InvoiceController : CommonApiController
{
    public async Task<IHttpActionResult> Post([FromBody]Invoice invoice)
    {
        if(User.IsInRole("Readonly"))
        {
            return Forbidden();
        }

        // Rest of code

    }
}
24
Intrepid

デフォルトでは、アクションがvoidを返す場合、応答のHTTPステータスは204になるため、_no-content_の結果に便利なメソッドはありません。

アクションで明示的に指定したい場合は、アクションからStatusCode(HttpStatusCode.NoContent)を返すか、

_ResponseMessage(new HttpResponseMessage(HttpStatusCode.NoContent)).
_

Unauthorized()簡易メソッドは401ステータスを提供するため、Forbidden(403)の場合は、StatusCode(HttpStatusCode.Forbidden)または

_ResponseMessage(new HttpResponseMessage(HttpStatusCode.Forbidden))
_
48

@Intrepid実装を試してみましたが、いくつかの問題に遭遇しました。ここに2つの解決策があります:

解決策1:パート:return Forbidden();は機能しません。

コンパイラはこれを認識しません。

代わりに:return new ForbiddenResult(Request, "my reason");

更新1

解決策2:

これは@Interpidが実装で意図したものだと思いますが、彼はいくつかのことを逃していました。

return Forbidden();を使用するには、CommonApiControllerIHttpActionResultのカスタムForbiddenを返す関数でNoContentを更新する必要があります

クラスは次のようになります。

public abstract class CommonApiController: ApiController {

    protected ForbiddenResult Forbidden() {
     return new ForbiddenResult(this.Request);
    }

    protected ForbiddenResult Forbidden(string reason) {
     return new ForbiddenResult(this.Request, reason);
    }

    protected NoContentResult NoContent() {
     return new NoContentResult(this.Request);
    }

    public class ForbiddenResult: IHttpActionResult {
     private readonly HttpRequestMessage _request;
     private readonly string _reason;

     public ForbiddenResult(HttpRequestMessage request, string reason) {
      _request = request;
      _reason = reason;
     }

     public ForbiddenResult(HttpRequestMessage request) {
      _request = request;
      _reason = "Forbidden";
     }

     public Task < HttpResponseMessage > ExecuteAsync(CancellationToken cancellationToken) {
      var response = _request.CreateResponse(HttpStatusCode.Forbidden, _reason);
      return Task.FromResult(response);
     }
    }

    public class NoContentResult: IHttpActionResult {
     private readonly HttpRequestMessage _request;
     private readonly string _reason;

     public NoContentResult(HttpRequestMessage request, string reason) {
      _request = request;
      _reason = reason;
     }

     public NoContentResult(HttpRequestMessage request) {
      _request = request;
      _reason = "No Content";
     }

     public Task < HttpResponseMessage > ExecuteAsync(CancellationToken cancellationToken) {
      var response = _request.CreateResponse(HttpStatusCode.NoContent, _reason);
      return Task.FromResult(response);
     }
    }
   }

とにかく、私が間違っていて@Interpidの答えが正しければ。彼の実装を機能させるためにここで何が欠けていますか?

8
Asaf Epelbaum

ApiControllerにサブクラスを追加せずに、応答に理由フレーズを含める場合は、ResponseMessageオブジェクトを作成し、ResponseMessage()メソッドによってアクションからそれを返します。これを試して:

public class InvoiceController : ApiController
{
    public async Task<IHttpActionResult> Post([FromBody]Invoice invoice)
    {
        if(User.IsInRole("Readonly"))
        {
            var response = new HttpResponseMessage(HttpStatusCode.Forbidden);

            response.ReasonPhrase = "User has the Readonly role";
            return ResponseMessage(response);
        }

        // Rest of code

    }
}
3
kmac.mcfarlane

以下を使用できるようになりました(.Net Standard):

return StatusCode(HttpStatusCode.NoContent);

または(.Net Core 2.1+)

return NoContent();
2
Scott Wendt

これは私にとってはうまくいきました:

public class CodeAndReason : IHttpActionResult
{
    private readonly HttpStatusCode code;
    private readonly string reason;

    public CodeAndReason(HttpStatusCode code, string reason)
    {
        this.code = code;
        this.reason = reason;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(code)
        {
            ReasonPhrase = reason,
            Content = new StringContent(reason),
        };

        return Task.FromResult(response);
    }

    public static IHttpActionResult NotFound(string reason)
    {
        return new CodeAndReason(HttpStatusCode.NotFound, reason);
    }

    public static IHttpActionResult Conflict(string reason)
    {
        return new CodeAndReason(HttpStatusCode.Conflict, reason);
    }

    public static IHttpActionResult Unauthorized(string reason)
    {
        return new CodeAndReason(HttpStatusCode.Unauthorized, reason);
    }
}

使用されます:

return CodeAndReason.NotFound("Record {blah} not found");
2
joehoper