如何仅为一个 Razor 页面设置 `ValidationVisitor.MaxValidationDepth` = 1?

2023-12-29

我该如何改变ValidationVisitor.MaxValidationDepth在本地为一个 Razor 页面阻止验证子对象?

我不想在全球范围内改变它MvcOptions.MaxValidationDepth就像文档中描述的那样:最大递归 https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-5.0#maximum-recursion

这是一个跟随问题。请检查我原来的问题以查看此处的对象结构:​

复杂对象的 Razor 页面验证错误,TryValidateModel() 不起作用 https://stackoverflow.com/q/67348699/248756


我们可以从IObjectModelValidator。默认实现是内部的(DefaultObjectValidator)并继承自ObjectModelValidator。基(和抽象)类要求派生类仅实现一种称为GetValidationVisitor。这是您修改的一个扩展点MaxValidationDepth of the ValidationVisitor在它运行之前。默认实现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;
    }
}

最后我们需要注册您的自定义IObjectModelValidator在 - 的里面Startup.ConfigureServices:

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));

Use it:

//suppose you want it to be 1
//for this specific page
[MaxValidationDepth(1)]
public class YourPageModel : PageModel {
     //...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何仅为一个 Razor 页面设置 `ValidationVisitor.MaxValidationDepth` = 1? 的相关文章

随机推荐

  • 如何将依赖于 jQuery 的 Javascript 小部件嵌入到未知环境中

    我正在开发一个依赖于 jQuery 的 javascript 小部件 该小部件可能会也可能不会加载到已加载 jQuery 的页面上 在这种情况下会出现很多问题 如果网页没有jQuery 我必须加载我自己的jQuery 然而 这样做时似乎存在
  • 在rails应用程序中使用google图表api - 使用arrayToDataTable时如何在系列中指定空(缺失)值

    我的应用程序使用谷歌图表 API 绘制 4 个数据系列的图表 控制器加载一个数组 视图有谷歌图表 JavaScript 来绘制购物车 如果数组已满 它就可以工作 但当然有时数据系列会丢失一些点 并且我看不到如何指定系列中的 丢失 数据点 因
  • 如何在程序结束时关闭数据库连接?

    在Java程序中 我有一个单例类来保存数据库连接 该连接由整个程序使用 如何告诉Java在程序结束时关闭连接 我可以在 main 末尾放置一个 connection close 语句 但是如果程序意外结束 例如 由于程序中某处未捕获的异常或
  • PHP 在编辑模式下显示下拉列表中选定的值

    这个问题已经被问过 但我的问题很简单 在我的帐户页面中 我在下拉列表中显示了员工所在国家 地区 在编辑模式下如何选择组合中的值 假设您的用户所在国家 地区是 user country以及所有国家 地区的列表 all countries ar
  • 如何从c#返回List并通过com在vc++中使用它

    如何从 C 方法返回 List 以及在 C 中使用 List 返回值 您可以指导如何操作吗 我将按照我的完整方案进行操作 在 c DemoLib cs 中 usng System using System Collections Gener
  • 使用 ffmpeg 命令在视频中添加多个元数据

    添加单个元数据的命令工作正常 ffmpeg i var www html public uploads wp video akka mov metadata kKeyContentIdentifier com apple quicktime
  • 在 numpy 一维数组中查找拐点和驻点

    假设我有以下 numpy 数组 import numpy as np import matplotlib pyplot as plt x np array 11 53333333 11 86666667 11 1 10 66666667 1
  • 无法更改 unicode 字符的字体颜色

    确实很小的事情 但我在 Joomla 前端编辑页面的发布按钮上有这些日历图标 我为此使用 Unicode 字符 U 1F5D2 但我似乎无法使用 CSS 更改其颜色 我试图将其变成白色 浏览器检查员说它是白色的 但显然不是 请参阅此处的示例
  • 在 ARMv8-A Linux 上禁用 CPU 缓存 (L1/L2)

    我想在运行 Linux 的 ARMv8 A 平台上禁用低级缓存 以便独立于缓存访问来测量优化代码的性能 对于英特尔系统 我找到了以下资源 有没有办法在 Linux 系统上禁用 CPU 缓存 L1 L2 https stackoverflow
  • TensorFlow - Saver.restore 未恢复所有参数

    我训练了双向 LSTM 类型的 RNN 近 24 小时 由于误差波动 我决定在允许其继续训练之前减少学习量 由于模型在每个时期都使用 Saver save sess file 保存 因此我终止了训练 CTC 损失已最小化至大约 115 现在
  • 使用 gruntjs 组合并缩小所有 Bower 库

    有没有办法自动将所有 Bower 安装的库合并并缩小为 1 个文件 首先我尝试了最基本的方法 将所有 js所有子目录中的文件 uglify options compress true my target files vendor js bo
  • 如何禁用 libsvm (java) 中的控制台输出

    我正在使用 libsvmjava并且遇到了与描述类似的问题here https stackoverflow com questions 8302519 suppressing the output in libsvm python对于蟒蛇
  • 如何捕获java.sql.SQLIntegrityConstraintViolationException?

    我的应用程序使用 JPA JavaDB 当我尝试保留违反约束的对象时 我得到SQLIntegrityConstraintViolationException http docs oracle com javase 7 docs api ja
  • 为什么 Mongoose 不验证更新?

    我有这个代码 var ClientSchema new Schema name type String required true trim true var Client mongoose model Client ClientSchem
  • 导航控制器栏被切断

    如果通过选择隐藏状态栏status bar style hide during application launch我正在自定义导航栏 如下所示 UINavigationBar appearance setBackgroundImage U
  • 以日历日为单位分割间隔的持续时间

    我有以下数据集 显示一集的开始和结束 日期和时间 ep lt data frame start c 2009 07 13 23 45 00 2009 08 14 08 30 00 2009 09 16 15 30 00 end c 2009
  • “POSIX”是什么意思?

    什么是 POSIX 我已阅读维基百科文章 http en wikipedia org wiki POSIX每次遇到这个词我都会读它 事实是我从来没有真正理解它是什么 任何人都可以通过解释 POSIX 的需要 来向我解释一下吗 POSIX h
  • 尝试混合属于不同事务的对象

    pony orm core TransactionError An attempt to mix objects belonging to different transactions 我知道这个错误是描述性的 我只是不明白为什么会发生 我
  • HikariCP 连接过多

    我有一个Java Servlet 我想将连接池与jdbc 数据库 mysql 一起使用 所以这就是我正在做的 这个类是公共最终类DBConnector private static final HikariDataSource dataSo
  • 如何仅为一个 Razor 页面设置 `ValidationVisitor.MaxValidationDepth` = 1?

    我该如何改变ValidationVisitor MaxValidationDepth在本地为一个 Razor 页面阻止验证子对象 我不想在全球范围内改变它MvcOptions MaxValidationDepth就像文档中描述的那样 最大递