如何从 Invoke 方法返回 BadRequestObjectResult

我正在开发一个 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 class

public class Error

{

    public async static Task<ObjectResult> Error(string message, logger log)

    {

       //logic for creating the payload

       return new BadRequestObjectResult(errorMessagePayload)

    }

}


//Startup class configure method

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

{

     app.UseMiddleware<AcceptHeaderMiddleware>();

     if (env.IsDevelopment())

     {   

         app.UseDeveloperExceptionPage();

     }

     else

     {          

         app.UseHsts();

     }


     app.UseMvc();

}

我期待 badObjectResult(当验证失败时)作为响应,但我得到 200 OK 响应和空白响应正文。


慕少森
浏览 171回答 1
1回答

泛舟湖上清波郎朗

这些IActionResult类型仅在 MVC 管道中使用。作为该管道的一部分,来自操作或 MVC 筛选器的结果对象随后被执行以创建对HttpResponse对象的实际响应。然而,这意味着您实际上不能在 MVC 管道之外使用操作结果对象。因此,如果您有自定义中间件,您将无法使用这些结果,因为它们不会被 MVC 管道处理(从技术上讲,您可以自己执行结果,但我不建议这样做)。因此,您必须自己设置结果。如果您只想设置一些(失败)状态代码,那很容易做到:public async Task<ObjectResult> Invoke(HttpContext context){&nbsp; &nbsp; bool result = context.Request.Headers["Accept"].ToString() == "app/version.abc-ghi-api.v";&nbsp; &nbsp; if (result)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; await&nbsp; _next(context);&nbsp; &nbsp;&nbsp; &nbsp; }&nbsp; &nbsp; else&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; context.Result.StatusCode = 500;&nbsp; &nbsp; }}如果你想包含一个主体,那么它会变得有点复杂,因为你现在必须写入输出流,这也意味着你首先必须正确地序列化你的输出。因此,与其在自定义中间件中执行此操作,我建议您在 MVC 过滤器中执行此操作。如上所述,过滤器作为 MVC 管道的一部分运行,因此它们仅与 MVC 中间件一起运行。这意味着您将无法以这种方式保护您的静态文件——但通常这没什么大不了的。在您的情况下,由于您想通过 HTTP 标头授权客户端,我建议您创建一个授权过滤器:public class AcceptHeaderAuthorizationFilter : IAuthorizationFilter{&nbsp; &nbsp; public void OnAuthorization(AuthorizationFilterContext context)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; bool result = context.HttpContext.Request.Headers["Accept"].ToString() == "app/version.abc-ghi-api.v";&nbsp; &nbsp; &nbsp; &nbsp; if (!result)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var result = new Error.GenerateErrorMessage("Accept header validation failed", Log.Logger);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context.Result = result;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}这现在使用 MVC 管道,因此您可以使用IActionResult对象。由于您在授权过滤器中设置了结果,因此您也将剩余的管道短路,因此之后不会执行任何操作。执行将停止并立即产生您的结果。最后一点:Accept标头有一个非常具体的用例,用于内容协商。这意味着当您将其设置为某种自定义内容类型时,服务器将返回具有此类内容类型的结果。将它用于授权目的并不适合这里。
打开App,查看更多内容
随时随地看视频慕课网APP