如何从 IActionResult 中检索 HTTP 代码和内容?

Ric*_*d77 12 c# asp.net-core-mvc asp.net-core

我的控制器中有 7 个操作。我重构了它们并能够隔离公共部分。

public IActionResult Get()
{
    var response = CommonCode();
}

public IActionResult Get(guid id)
{
    var response = CommonCode();
}

public IActionResult Post(ViewModel vm)
{
    var response = CommonCode();
}
Run Code Online (Sandbox Code Playgroud)

这是我重构公共代码的地方。

provate IActionResult CommonCode()
{
   if(userHasNoPermission())
     return Forbid();

   if(IdProvidedDoesntExist())
     return BadRequest();

   //...
}
Run Code Online (Sandbox Code Playgroud)

当我查看 内部时response,我只看到一种方法:ExecuteResultAsync()

有没有办法检索我在辅助方法中发送的 HTTP 代码?

例如,我想停止处理(如果是)500,检索消息以添加到ModelState*(如果是)400,但如果是,则继续OK

Joe*_*ers 11

有一些“肮脏”的方法可以在没有案例陈述的情况下做到这一点。状态代码实际上在结果中,但 IActionResult 和 ActionResult 讨厌被转换为通用类型。

此示例从任何常见结果中获取 IActionResult 并使用反射提取状态代码。如果您不介意这样做,则可以节省 case 语句进行模式匹配的要求。对于内容也可以这样做。

    public static HttpStatusCode GetHttpStatusCode(IActionResult functionResult)
    {
        try
        {
            return (HttpStatusCode)functionResult
                .GetType()
                .GetProperty("StatusCode")
                .GetValue(functionResult, null);
        }
        catch
        {
            return HttpStatusCode.InternalServerError;
        }
    } 
Run Code Online (Sandbox Code Playgroud)


Thi*_*ago 9

Ok()我在返回时也遇到了类似的问题NotFound()。我能够使用该IStatusCodeActionResult界面获取状态代码。

((IStatusCodeActionResult)response).StatusCode;


Chr*_*att 7

返回的CommonCode只是某种类型的IActionResult. “结果”实际上并不是“反应”。当操作完全返回到请求管道时(当您直接在代码中调用该方法时尚未发生),就会发生这种情况。因此,像 HTTP 状态代码这样的概念甚至还不相关。如果您返回类似 的内容StatusCodeResult,那么从技术上讲,这只是建议的状态代码。如果请求管道稍后出现异常,或者某些中间件由于某种原因显式更改状态代码,那么情况将会有所不同。

总而言之,你试图将两个不相关的事物混为一谈。我认为您只是想知道 中发生了什么CommonCode,并认为 HTTP 状态是确定这一点的最佳方法。实际上,返回一个元组或执行诸如模式匹配之类的操作会更好:

使用元组,您基本上可以从方法中返回多个内容CommonCode。例如,您可以执行以下操作:

private (int, IActionResult) CommonCode()
{
   if(userHasNoPermission())
     return (403, Forbid());

   if(IdProvidedDoesntExist())
     return (400, BadRequest());

   //...
}
Run Code Online (Sandbox Code Playgroud)

然后:

public IActionResult Get()
{
    (var status, var response) = CommonCode();
    // branch on `status`
}
Run Code Online (Sandbox Code Playgroud)

或者,使用模式匹配:

public IActionResult Get()
{
    var response = CommonCode();
    switch (response)
    {
        case ForbidResult forbid:
            // do something for forbidden
            break;
        case BadRequestResult badRequest:
            // do something for bad request
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)