创建新的 IHttpActionResult 操作结果方法

Creating new IHttpActionResult action result methods

有没有一种方法可以使用新的 IHttpActionResult 界面来 return HttpStatusCode.NoContent 响应消息?

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

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

添加其他结果类型是否容易?

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

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

ResponseMessage(new HttpResponseMessage(HttpStatusCode.NoContent)).

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

ResponseMessage(new HttpResponseMessage(HttpStatusCode.Forbidden))

我发现这个 example site 显示了如何添加自定义 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

    }
}

如果您想在响应中包含原因短语而不向 ApiController 添加子class,请构建一个 ResponseMessage 对象,并通过 ResponseMessage() 方法从操作中 return 它。试试这个:

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

    }
}

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

解决方案一: 部分:return Forbidden(); 不应该工作。

编译器无法识别。

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

更新 1

方案二:

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

为了使用 return Forbidden();CommonApiController 应该使用 return 自定义 IHttpActionResult 用于 Forbidden 和 [=17= 的功能进行更新]

class 应该是这样的:

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 的回答是正确的。为了使他的实施工作,我在这里缺少什么?

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

return StatusCode(HttpStatusCode.NoContent);

或(.Net Core 2.1+)

return NoContent();

这对我来说效果很好:

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