本文介绍了如何只为一个Razor Page设置`ValidationVisitor.MaxValidationDepth`=1?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
如何在本地更改一个Razor页的ValidationVisitor.MaxValidationDepth
以阻止验证子对象?
我不想像文档:Maximum recursion
那样使用MvcOptions.MaxValidationDepth
全局更改它
这是一个后续问题。请检查我的原始问题以查看此处的对象结构:
Razor Page validation error with a complex object, TryValidateModel() does not work
推荐答案
我们可以从IObjectModelValidator
开始。默认实现是内部实现(DefaultObjectValidator
),继承自ObjectModelValidator
。基类(和抽象类)要求派生类只实现一个名为GetValidationVisitor
的方法。这是您需要在ValidationVisitor
运行之前修改MaxValidationDepth
的一个扩展点。默认实现DefaultObjectValidator
只是将MaxValidationDepth
设置为从MvcOptions
获得的值。因此,正如您所说,它在全球范围内应用。
在IObjectModelValidator
的自定义实现中(当然我们让它继承自ObjectModelValidator
),您可以改为从当前上下文获取MaxValidationDepth
。
MaxValidationDepth
。要使其成为标准(像横切关注点一样使用),我们可以创建一个IAsyncPageFilter
作为属性,该属性可以应用于您想要的任何页面模型类。
实现代码如下:
//the custom IObjectModelValidator (which is much like what from the source code
//of DefaultObjectValidator)
public class ContextBasedObjectModelValidator : ObjectModelValidator
{
readonly MvcOptions _mvcOptions;
public ContextBasedObjectModelValidator(IModelMetadataProvider modelMetadataProvider,
IList<IModelValidatorProvider> validatorProviders,
MvcOptions mvcOptions) : base(modelMetadataProvider, validatorProviders)
{
_mvcOptions = mvcOptions;
}
public override ValidationVisitor GetValidationVisitor(ActionContext actionContext,
IModelValidatorProvider validatorProvider,
ValidatorCache validatorCache,
IModelMetadataProvider metadataProvider,
ValidationStateDictionary validationState)
{
var visitor = new ValidationVisitor(
actionContext,
validatorProvider,
validatorCache,
metadataProvider,
validationState)
{
MaxValidationDepth = actionContext.HttpContext.Features.Get<IContextBasedMaxValidationDepthFeature>()?.MaxValidationDepth ?? _mvcOptions.MaxValidationDepth,
ValidateComplexTypesIfChildValidationFails = _mvcOptions.ValidateComplexTypesIfChildValidationFails,
};
return visitor;
}
}
//we need a class for the custom request feature to hold your context-based MaxValidationDepth
public interface IContextBasedMaxValidationDepthFeature
{
int MaxValidationDepth { get; }
}
public class ContextBasedMaxValidationDepthFeature : IContextBasedMaxValidationDepthFeature
{
public ContextBasedMaxValidationDepthFeature(int maxValidationDepth)
{
MaxValidationDepth = maxValidationDepth;
}
public int MaxValidationDepth { get; }
}
//here the page filter to help set your context-based MaxValidationDepth
[AttributeUsage(AttributeTargets.Class)]
public class MaxValidationDepthAttribute : Attribute, IAsyncPageFilter
{
public MaxValidationDepthAttribute(int maxValidationDepth)
{
MaxValidationDepth = maxValidationDepth;
}
public int MaxValidationDepth { get; }
public Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
//set the max validation depth from the predefined value (via the attribute)
context.HttpContext.Features
.Set<IContextBasedMaxValidationDepthFeature>(new ContextBasedMaxValidationDepthFeature(MaxValidationDepth));
return next();
}
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
return Task.CompletedTask;
}
}
最后,我们需要在Startup.ConfigureServices
中注册您的自定义IObjectModelValidator
:
services.Replace(new ServiceDescriptor(typeof(IObjectModelValidator), sp => {
var options = sp.GetRequiredService<IOptions<MvcOptions>>().Value;
var metadataProvider = sp.GetRequiredService<IModelMetadataProvider>();
return new ContextBasedObjectModelValidator(metadataProvider, options.ModelValidatorProviders, options);
}, ServiceLifetime.Singleton));
使用它:
//suppose you want it to be 1
//for this specific page
[MaxValidationDepth(1)]
public class YourPageModel : PageModel {
//...
}
这篇关于如何只为一个Razor Page设置`ValidationVisitor.MaxValidationDepth`=1?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!