ASP.net 核心 API:验证访问者超出了配置的最大验证深度'32'



AS从docker容器运行ASP.Net核心web API时,抛出验证错误:

System.InvalidOperationException:ValidationVisitor在验证类型"ClassName"时超过了配置的最大验证深度"32"。这可能表示一个非常深入或无限递归的对象图。请考虑修改"MvcOptions.MaxValidationDepth"或取消对模型类型的验证。

我唯一能找到关于这个问题的讨论的地方是在这里,似乎已经对ASP.net核心的最新版本进行了修复。我将.net核心版本更新为最新版本,但仍然面临同样的问题
这是验证导致问题的类的代码:

[Required]
[Range(1, long.MaxValue)]
public long Id { get; set; }
[Required(AllowEmptyStrings = false)]
[StringLength(1000)]
public string Name { get; set; }
[Required(AllowEmptyStrings = false)]
[StringLength(200)]
public string Category { get; set; }
[Required(AllowEmptyStrings = false)]
[StringLength(13)]
public string Division { get; set; }

重要:我是唯一一个面临这个问题的人,因为我的团队其他成员都在成功地运行项目,我们非常感谢您的帮助。

这是Asp.Net Core ModelBinding Validation中影响MVC和Web-Api的一个错误https://github.com/dotnet/aspnetcore/issues/13778

一种解决方法是增加Startup.ConfigureServices:中的MaxModelValidationErrors

services.AddMvc()
.AddMvcOptions(options => {
options.MaxModelValidationErrors = 999999;
})

增加MaxModelValidationErrors并不能解决问题,我不得不更改一个不同的值(MaxValidationDepth(才能让事情正常工作。我想把它添加到这里,以防有人和我有同样的问题。

.AddMvcOptions(options =>
{
options.MaxValidationDepth = 999;
});

您可以在Startup.ConfigureServices:中增加MaxModelValidationErrors

services.AddControllers(options =>
{
options.MaxModelValidationErrors = 999999;
});

我不再推荐SuppressChildValidationMetadataProvider。

但是你可以使用这个属性:

using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
[ValidateNever]
public List<ToNotValidateSet> ToNotValidateSet { get; set; }

在所有不应该验证的虚拟属性上。

我正在将一个项目升级到.NET6,遇到了此错误消息。上面的解决方案没有修复它。验证错误引用了一个虚拟子属性和一个已验证的东西,我现在甚至不想验证它。

这为我修复了它:

services.AddMvc(option => {
//fix: max validation depth error in TryValidateModel(model) since .NET6
option.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(MyVirtualSubpropertyClassThatShouldNotBeValidated)));
});

免责声明:我很清楚这是一个快速修复,可能会产生副作用。此外,我不能花一周的时间来妥善修复它,现在只想要一个工作版本。

对我来说,问题是我使用了实体框架核心的延迟加载。

验证器将递归遍历模型,并通过延迟加载获取所有绑定属性。

由于我的模型有很多循环,它会无限期地验证它,但默认情况下,验证器会在递归深度级别32停止并抛出异常。

您可以通过设置MaxValidationDepth来增加级别的数量,但它只会工作更长时间,产生相同的结果。

如果我们能告诉验证器在某种程度上停止(而不抛出错误(,那就太好了,但没有这样的选择。

事实上,我只想验证我的模型的第一级属性,而不想再深入下去。

首先获得分离的模型可以解决问题,但我的API不允许这样做

所以这里是我现在使用的变通方法:

public T GetDetachedModel<T>(T model) where T : new() 
{
T detachedModel = new T();
foreach (var p in typeof(T).GetProperties())
{
if (!(p.GetAccessors()?[0].IsVirtual ?? false))
{
p.SetValue(detachedModel, p.GetValue(model, null));
}
}
return detachedModel;
}

延迟加载要求将所有映射的属性声明为虚拟。我们通过创建新对象和成员复制非虚拟属性来利用这一事实。

";分离的";模型可以用来代替原来的模型。

最新更新