如何从 Invoke 方法 return BadRequestObjectResult
How to return BadRequestObjectResult from Invoke method
我正在开发一个 API,它最初验证来自 https 请求的接受 header,然后通过中间件进行响应。我已经在调用方法中添加了验证 Accept header 的逻辑,如图所示,How do I return bad request object if the result of the validation(string comparison) is false.
//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 响应和空白响应 body。
IActionResult
类型仅在 MVC 管道中使用。作为该管道的一部分,然后执行操作或 MVC 过滤器的结果 objects 以在 HttpResponse
object.
上创建实际响应
然而,这意味着您实际上不能在 MVC 管道之外使用操作结果 objects。因此,如果您有自定义中间件,您将无法使用这些结果,因为它们不会被 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;
}
}
如果你想包含一个 body,那么它会变得有点复杂,因为你现在必须写入输出流,这也意味着你首先必须正确地序列化你的输出。
因此,与其在自定义中间件中执行此操作,我建议您在 MVC 过滤器中执行此操作。如上所述,filters运行作为MVC管道的一部分,所以它们只运行与MVC中间件有关。这意味着您将无法以这种方式保护您的静态文件——但通常这没什么大不了的。
在您的情况下,由于您想通过 HTTP header 授权客户端,我建议您创建一个 authorization filter:
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
objects。由于您在授权过滤器中设置结果,因此您也是 short-circuiting 剩余的管道,因此之后不会执行任何操作。执行将停止并立即产生您的结果。
最后一点:Accept
header 有一个非常具体的用例,用于内容协商。这意味着当您将其设置为某种自定义内容类型时,服务器应 return 具有此类内容类型的结果。将它用于授权目的并不适合这里。
我正在开发一个 API,它最初验证来自 https 请求的接受 header,然后通过中间件进行响应。我已经在调用方法中添加了验证 Accept header 的逻辑,如图所示,How do I return bad request object if the result of the validation(string comparison) is false.
//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 响应和空白响应 body。
IActionResult
类型仅在 MVC 管道中使用。作为该管道的一部分,然后执行操作或 MVC 过滤器的结果 objects 以在 HttpResponse
object.
然而,这意味着您实际上不能在 MVC 管道之外使用操作结果 objects。因此,如果您有自定义中间件,您将无法使用这些结果,因为它们不会被 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;
}
}
如果你想包含一个 body,那么它会变得有点复杂,因为你现在必须写入输出流,这也意味着你首先必须正确地序列化你的输出。
因此,与其在自定义中间件中执行此操作,我建议您在 MVC 过滤器中执行此操作。如上所述,filters运行作为MVC管道的一部分,所以它们只运行与MVC中间件有关。这意味着您将无法以这种方式保护您的静态文件——但通常这没什么大不了的。
在您的情况下,由于您想通过 HTTP header 授权客户端,我建议您创建一个 authorization filter:
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
objects。由于您在授权过滤器中设置结果,因此您也是 short-circuiting 剩余的管道,因此之后不会执行任何操作。执行将停止并立即产生您的结果。
最后一点:Accept
header 有一个非常具体的用例,用于内容协商。这意味着当您将其设置为某种自定义内容类型时,服务器应 return 具有此类内容类型的结果。将它用于授权目的并不适合这里。