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

时间:2018-06-21 16:23:34

标签: c# asp.net-core asp.net-core-mvc

我的控制器中有7个动作。我已经对其进行了重构,从而能够隔离公共部分。

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

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

public IActionResult Post(ViewModel vm)
{
    var response = CommonCode();
}

这是我重构通用代码的地方。

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

   if(IdProvidedDoesntExist())
     return BadRequest();

   //...
}

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

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

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

3 个答案:

答案 0 :(得分:2)

您可以从private方法返回状态代码本身。 例如

private IActionResult CommonCode() {    
    if(userHasNoPermission())
     return StatusCode(401);

   if(IdProvidedDoesntExist())
     return StatusCode(400);

   //... }

然后在您的方法中进行检查

public IActionResult Post(ViewModel vm)
{
    var response = CommonCode();
    if (this.HttpContext.Response.StatusCode = 418)
       Console.WriteLine("I'm a teapot")

    else {
       return response;
       }
}

答案 1 :(得分:1)

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

总之,您正在尝试将两个无关的内容合并在一起。我认为您只是想知道CommonCode中发生了什么,并认为HTTP状态是确定此情况的最佳方法。实际上,最好返回一个元组或执行类似于模式匹配的操作:

使用元组,基本上可以从CommonCode方法返回一件事。例如,您可以执行以下操作:

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

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

   //...
}

然后:

public IActionResult Get()
{
    (var status, var response) = CommonCode();
    // branch on `status`
}

或者,通过模式匹配:

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;
    }
}

答案 2 :(得分:0)

有几种“肮脏”的方法可以在没有案例说明的情况下进行操作。状态代码实际上位于结果中,但是IActionResult和ActionResult讨厌被强制转换为通用类型。

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

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