为了账号安全,请及时绑定邮箱和手机立即绑定

如何从 Invoke 方法返回 BadRequestObjectResult

如何从 Invoke 方法返回 BadRequestObjectResult

C#
慕少森 2022-12-24 13:59:14
我正在开发一个 API,它最初验证来自 https 请求的 Accept 标头,然后通过中间件进行响应。我已经在 Invoke 方法中添加了验证 Accept 标头的逻辑,如图所示,如果验证结果(字符串比较)为假,我如何返回错误的请求对象。//Invoke method public async Task<ObjectResult> Invoke(HttpContext context){   bool result = context.Request.Headers["Accept"].ToString() ==    "app/version.abc-ghi-api.v";   if (result == true)   {     await  _next(context);      }   ObjectResult objectResult = await    Error.GenerateErrorMessage("Accept header validation    failed", Log.Logger);   return objectResult;  }//Error classpublic class Error{    public async static Task<ObjectResult> Error(string message, logger log)    {       //logic for creating the payload       return new BadRequestObjectResult(errorMessagePayload)    }}//Startup class configure methodpublic void Configure(IApplicationBuilder app, IHostingEnvironment env){     app.UseMiddleware<AcceptHeaderMiddleware>();     if (env.IsDevelopment())     {            app.UseDeveloperExceptionPage();     }     else     {                   app.UseHsts();     }     app.UseMvc();}我期待 badObjectResult(当验证失败时)作为响应,但我得到 200 OK 响应和空白响应正文。
查看完整描述

1 回答

?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

这些IActionResult类型仅在 MVC 管道中使用。作为该管道的一部分,来自操作或 MVC 筛选器的结果对象随后被执行以创建对HttpResponse对象的实际响应。


然而,这意味着您实际上不能在 MVC 管道之外使用操作结果对象。因此,如果您有自定义中间件,您将无法使用这些结果,因为它们不会被 MVC 管道处理(从技术上讲,您可以自己执行结果,但我不建议这样做)。


因此,您必须自己设置结果。如果您只想设置一些(失败)状态代码,那很容易做到:


public async Task<ObjectResult> Invoke(HttpContext context)

{

    bool result = context.Request.Headers["Accept"].ToString() == "app/version.abc-ghi-api.v";

    if (result)

    {

        await  _next(context);   

    }

    else

    {

        context.Result.StatusCode = 500;

    }

}

如果你想包含一个主体,那么它会变得有点复杂,因为你现在必须写入输出流,这也意味着你首先必须正确地序列化你的输出。


因此,与其在自定义中间件中执行此操作,我建议您在 MVC 过滤器中执行此操作。如上所述,过滤器作为 MVC 管道的一部分运行,因此它们仅与 MVC 中间件一起运行。这意味着您将无法以这种方式保护您的静态文件——但通常这没什么大不了的。


在您的情况下,由于您想通过 HTTP 标头授权客户端,我建议您创建一个授权过滤器:


public class AcceptHeaderAuthorizationFilter : IAuthorizationFilter

{

    public void OnAuthorization(AuthorizationFilterContext context)

    {

        bool result = context.HttpContext.Request.Headers["Accept"].ToString() == "app/version.abc-ghi-api.v";

        if (!result)

        {

            var result = new Error.GenerateErrorMessage("Accept header validation failed", Log.Logger);

            context.Result = result;

        }

    }

}

这现在使用 MVC 管道,因此您可以使用IActionResult对象。由于您在授权过滤器中设置了结果,因此您也将剩余的管道短路,因此之后不会执行任何操作。执行将停止并立即产生您的结果。


最后一点:Accept标头有一个非常具体的用例,用于内容协商。这意味着当您将其设置为某种自定义内容类型时,服务器将返回具有此类内容类型的结果。将它用于授权目的并不适合这里。


查看完整回答
反对 回复 2022-12-24
  • 1 回答
  • 0 关注
  • 155 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信