我花了几乎一整天的时间来调试为什么我的客户端无法发布任何表单,直到我发现客户端的防伪机制被破坏,服务器只响应了
400
错误,日志为零或信息(结果是防伪验证以 Info
级别在内部记录)。
所以我决定服务器需要特殊处理这种情况,但是根据这个答案我真的不知道该怎么做(除了黑客攻击)。
通常我会设置一个
IAlwaysRunResultFilter
并检查 IAntiforgeryValidationFailedResult
。简单。
除了我使用 Api 控制器,所以默认情况下所有结果都会转换为
ProblemDetails
。所以 context.Result
正如这里提到的 始终是 ObjectResult
类型。那里接受的解决方案是使用 options.SuppressMapClientErrors = true;
,但是我想在管道末尾保留此映射。但如果这个选项没有设置为true,我不知道如何在这个转换之前拦截管道中的Result
。
所以就我而言,我想对链接帖子中提到的防伪验证结果做一些事情,但之后我想保留
ProblemDetails
转换。但我的问题一般标题为,它是关于在上述客户端映射过滤器之前执行过滤器。
通过黑客我能够实现我想要的。如果我们看一下源代码,我们可以看到我想要放在前面的过滤器的顺序为
-2000
。因此,如果我像这样注册全局过滤器o.Filters.Add(typeof(MyResultFilter), -2001);
,那么这里显示的过滤器会在ClientErrorResultFilter
之前正确执行,因此我可以处理结果并在处理后保留转换。然而,我觉得这只是利用 .Net 6 的开源性,当然,正如你所看到的,它是一个内部常量,所以我不能保证下一个补丁不会改变它并且我的代码会中断。当然,必须有一种正确的方法来命令我的过滤器在 api 转换之前运行。
我对模型验证过滤器管道的顺序也有类似的问题。如果模型无效,那么它会在进入控制器之前返回 400。
对于您的具体问题,您可以像这样阻止默认行为:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.ConfigureApiBehaviorOptions(o =>
{
// Disable `ClientErrorResultFilter`
o.SuppressMapClientErrors = true;
// ...
})
// ...
}
更多详细信息请参见:https://disklosr.com/posts/004-concient-error-response-format-asp-net-core-web-api/