How can I set `ValidationVisitor.MaxValidationDepth` = 1 only for one Razor Page?(如何只为一个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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何只为一个Razor Page设置`ValidationVisitor.MaxValidationDepth`=1?
基础教程推荐
- .NET SerialPort DataReceived 事件未触发 2022-01-01
- 如何使用 .Net 检查 Active Directory 服务器是否已启动并正在运行? 2022-01-01
- 我应该在后面的代码中直接使用 Linq To SQL 还是使 2022-01-01
- Moq It.Is<>不匹配 2022-01-01
- 如果有人提交恶意软件Nuget包怎么办? 2022-01-01
- 当值可以是对象或空数组时反序列化 JSON 2022-01-01
- 禁止输入少量字符,例如'<'、'&a 2022-01-01
- Azure Functions:CosmosDBTrigger 未在 Visual Studio 中触发 2022-01-01
- WPF 模态进度窗口 2022-01-01
- C# 从 List<List<int>> 中删除重 2022-01-01
