创建新的IHttpActionResult操作结果方法

时间:2015-02-05 11:46:06

标签: c# asp.net-web-api2

有没有办法可以使用新的IHttpActionResult界面返回HttpStatusCode.NoContent响应消息?

我目前正在使用return new HttpResponseMessage( HttpStatusCode.NoContent ); 并希望将其转换为return NoContent();

IHttpActionResult已经有Ok()Conflict()NotFound(),但我无法找到我需要使用的Forbidden()NoContent()在我的项目中。

添加其他结果类型有多容易?

6 个答案:

答案 0 :(得分:47)

no-content结果没有便捷方法,因为默认情况下,当某个操作返回void时,响应将具有HTTP状态204.

如果您希望明确指出在操作中,您还可以从您的操作中返回StatusCode(HttpStatusCode.NoContent)

ResponseMessage(new HttpResponseMessage(HttpStatusCode.NoContent)).

Unauthorized()方便方法为您提供401状态,因此对于Forbidden(403),您还必须使用StatusCode(HttpStatusCode.Forbidden)

ResponseMessage(new HttpResponseMessage(HttpStatusCode.Forbidden))

答案 1 :(得分:24)

我发现此example site显示了如何添加自定义IHttpActionResult方法,并且我已经使用它来创建Forbidden()NoContent()方法并取得了巨大成功。< / p>

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

    }
}

答案 2 :(得分:8)

我尝试了@Intrepid实现,但遇到了一些问题。我在这里看到两个解决方案:

解决方案1: 部分:return Forbidden();不应该有用。

编译器无法识别这一点。

应该是:return new ForbiddenResult(Request, "my reason");

更新1

解决方案2:

我认为这是@Interpid在实施中的意图,但他遗漏了一些东西。

要使用return Forbidden();CommonApiController应使用返回IHttpActionResultForbidden的自定义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的回答是正确的。我在这里错过了什么让他的实施工作?

答案 3 :(得分:3)

如果要在不向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

    }
}

答案 4 :(得分:1)

您现在可以使用以下(.Net标准):

return StatusCode(HttpStatusCode.NoContent);

或(.Net Core 2.1 +)

return NoContent();

答案 5 :(得分:0)

这对我来说很好:

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