.Net Web API return 具有特定类型但没有操作结果的状态码?

.Net Web API return statuscode with specific type without actionresult?

我正在创建一个网站 API 并且我正在使用特定的 return 类型,因为我已经做过很多次了。通常,return 状态代码并不重要,只要它符合 REST 约定,而框架确实这样做了,所以我将其保留为默认值。例如,这为我提供了大多数成功操作的状态代码 200 OK,并且使用特定类型有助于使用 swagger 等工具生成前端代码。 但是,通过这种方式,我无法修改 HTTP 响应的状态代码,并且我坚持使用通用状态代码,所以我不能说 return a 201 Created 状态代码作为成功注册的结果或创建了新项目。

documentation points to IActionResult and ActionResult<T> for specifying the actual status code, specifically, the use of convenience methods like Ok() Created() etc. My problem with this is that it not only enforces the return type on my controllers, it also adds parts I do not want to use (for example, in case of Created(), a CreatedResult dto) and I want my API to return as little info as required. Not to mention that a return type of Task<ActionResult<MyShinyDto>> looks painfully ugly. So I would rather avoid the use of these predefined types. I'm also aware that in this case, I would need to make use of the ProducesAttribute 告诉代码生成器工具如 swagger 关于 returned 类型和代码。

我已经使用 the MS docs on it 创建了一个通用的异常处理中间件,其中我根据我创建的状态代码映射异常设置了 return 状态代码,但我不想重新路由 每个通过中间件请求只是为了设置状态码。

所以真的没有其他方法可以做我想做的事吗?我想象 .Net 会有某种属性,我可以用 return 类型的指示来装饰控制器方法,但我找不到任何属性。我找到的最接近的是 ProducesAttribute,但它不会修改状态代码,它只是将其指示给代码生成工具。

我post在这里回答,以防有人需要类似的东西。

所以我最终创建了一个自定义的 ActionFilter 来完成这项工作,尽管我希望有一些更优雅的东西。

public class StatusCodeAttribute : ProducesResponseTypeAttribute, IActionFilter 
{
    private readonly int statusCode;
    public StatusCodeAttribute(HttpStatusCode statusCode) 
        :base((int)statusCode)
    {
        this.statusCode = (int)statusCode;
    }
    public void OnActionExecuted(ActionExecutedContext context)
    {
        context.HttpContext.Response.StatusCode = this.statusCode;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // not going to use this
        return;
    }
}

实施 IActionFilter interface gives you access to the context of an action call, and through it, the HttpContext itself, so you can set the status code manually (yeah, it was a wrong assumption that any means of redirection is needed). I used the HttpStatusCode 枚举以防止使用任意代码。

该实现还使用 ProducesResponseTypeAttribute 向代码编辑器指示响应状态代码。由于我们不使用通用 return 类型,因此确切的类型由 swagger 获取。此实现的唯一缺点是 Content-Type 不是。下图证明 swagger 确实在我的 EventController 上获取了数据,但它不知道 Contet-Type.

虽然还有改进的余地,但这基本上就是我所需要的。如果有人知道我的实施有任何缺点,请不要犹豫发表评论,尽管我认为以这种方式设置状态代码不会以任何方式有害,也不会成为性能障碍。

编辑

我忘了说我将控制器的基数 class 从 ControllerBase 更改为 Controller,因为此实现具有我在代码中使用的过滤器功能。