ASP.NET MVC 3 对嵌套对象的验证未按预期工作 - 验证子对象两次而不是父对象

2024-01-10

我正在尝试让 ASP.NET MVC 3 从复杂的嵌套对象生成表单。我发现了一种意外的验证行为,我不确定这是否是 DefaultModelBinder 中的错误。

如果我有两个对象,我们将“父对象”称为“OuterObject”,并且它具有“InnerObject”类型的属性(子对象):

    public class OuterObject : IValidatableObject
{
    [Required]
    public string OuterObjectName { get; set; }

    public InnerObject FirstInnerObject { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!string.IsNullOrWhiteSpace(OuterObjectName) && string.Equals(OuterObjectName, "test", StringComparison.CurrentCultureIgnoreCase))
        {
            yield return new ValidationResult("OuterObjectName must not be 'test'", new[] { "OuterObjectName" });
        }
    }
}

这是内部对象:

    public class InnerObject : IValidatableObject
{
    [Required]
    public string InnerObjectName { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!string.IsNullOrWhiteSpace(InnerObjectName) && string.Equals(InnerObjectName, "test", StringComparison.CurrentCultureIgnoreCase))
        {
            yield return new ValidationResult("InnerObjectName must not be 'test'", new[] { "InnerObjectName" });
        }
    }
}

您会注意到我对两者进行的验证..只是一些虚拟验证来说明某些值不能等于“测试”。

这是将在 (Index.cshtml) 中显示的视图:

@model MvcNestedObjectTest.Models.OuterObject
@{
    ViewBag.Title = "Home Page";
}

@using (Html.BeginForm()) {
<div>
    <fieldset>
        <legend>Using "For" Lambda</legend>

        <div class="editor-label">
            @Html.LabelFor(m => m.OuterObjectName)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(m => m.OuterObjectName)
            @Html.ValidationMessageFor(m => m.OuterObjectName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(m => m.FirstInnerObject.InnerObjectName)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(m => m.FirstInnerObject.InnerObjectName)
            @Html.ValidationMessageFor(m => m.FirstInnerObject.InnerObjectName)
        </div>

        <p>
            <input type="submit" value="Test Submit" />
        </p>
    </fieldset>
</div>
}

..最后是 HomeController:

    public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new OuterObject();
        model.FirstInnerObject = new InnerObject();
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(OuterObject model)
    {
        if (ModelState.IsValid)
        {
            return RedirectToAction("Index");
        }
        return View(model);
    }
}

您会发现,当模型通过 DefaultModelBinder 进行验证时,“InnerObject”中的“Validate”方法会被命中两次,但“OuterObject”中的“Validate”方法根本不会被命中。

如果您从“InnerObject”中取出 IValidatableObject,那么“OuterObject”上的 IValidatableObject 就会受到攻击。

这是一个错误,还是我应该期望它能以这种方式工作?如果我应该期待它,最好的解决方法是什么?


这个答案只是提供我刚刚想到的一种解决方法 - 所以它并不是真正的答案!我仍然不确定这是否是一个错误或最好的解决方法是什么,但这是一个选择。

如果您从“InnerObject”中删除自定义验证逻辑并将其合并到“OuterObject”中,它似乎工作正常。因此基本上,这通过只允许最顶层的对象进行任何自定义验证来解决该错误。

这是新的内部对象:

    //NOTE: have taken IValidatableObject off as this causes the issue - we must remember to validate it manually in the "Parent"!
public class InnerObject //: IValidatableObject
{
    [Required]
    public string InnerObjectName { get; set; }
}

这是新的 OuterObject(验证代码是从 InnerObject 窃取的):

    public class OuterObject : IValidatableObject
{
    [Required]
    public string OuterObjectName { get; set; }

    public InnerObject FirstInnerObject { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!string.IsNullOrWhiteSpace(OuterObjectName) && string.Equals(OuterObjectName, "test", StringComparison.CurrentCultureIgnoreCase))
        {
            yield return new ValidationResult("OuterObjectName must not be 'test'", new[] { "OuterObjectName" });
        }

        if (FirstInnerObject != null)
        {
            if (!string.IsNullOrWhiteSpace(FirstInnerObject.InnerObjectName) &&
                string.Equals(FirstInnerObject.InnerObjectName, "test", StringComparison.CurrentCultureIgnoreCase))
            {
                yield return new ValidationResult("InnerObjectName must not be 'test'", new[] { "FirstInnerObject.InnerObjectName" });
            }
        }
    }
}

这正如我所期望的那样,将验证错误正确地连接到每个字段。

这不是一个很好的解决方案,因为如果我需要将“InnerObject”嵌套在其他类中,它不会共享该验证 - 我需要复制它。显然,我可以在类上有一个方法来存储逻辑,但每个“父”类需要记住“验证”子类。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ASP.NET MVC 3 对嵌套对象的验证未按预期工作 - 验证子对象两次而不是父对象 的相关文章

  • Mvc ViewBag - 无法将 null 转换为“bool”,因为它是不可为 null 的值类型

    我想在生成某个视图时在控制器中将 bool 设置为 true 然后相应地更改视图的标题 这应该非常简单 但我得到的是 无法对空引用执行运行时绑定异常详细信息 Microsoft CSharp RuntimeBinder RuntimeBin
  • JavaScript 正则表达式否定精确的字符串匹配

    HTML JavaScript 中有没有办法编写正则表达式来否定精确的字符串匹配 我想确保输入不等于 foo 仅有的 foo 验证必须失败 但是 fooo 必须被允许 换句话说 我正在寻找这个正则表达式的否定
  • 部分 ASP.NET MVC 视图提交

    我是 ASP NET MVC 的新手 所以这个问题可能显得 愚蠢 抱歉 我的主视图中有一个部分视图 部分视图提交一个表单 调用 HomeController 内的操作方法 它与服务器验证配合得很好 问题是在发布后仅呈现部分视图 发布后如何呈
  • ASP.NET MVC 2 发行版本的实际调试符号

    我需要 ASP NET MVC 2 发布版本 通过 Web 平台安装程序安装的版本 中的实际调试符号 我知道我可以下载源代码 构建并使用其中的调试符号 但这种方法有几个问题 要求使用此版本的 DLL 重建所有其他依赖项 因为它未签名 如果您
  • 我应该迁移到 ASP.NET MVC 吗?

    我刚刚听了 StackOverflow 团队的第 17 期播客 他们对ASP NET MVC http www asp net mvc 我决定去看看 但首先 我想确定这是值得的 我已经为几天后开始的项目创建了一个基础 Web 应用程序 供其
  • Java Spring Rest 验证配置属性访问

    我有一个 Spring JSON RestAPI 它使用注释驱动的输入验证 Valid 当我尝试验证另一个对象内的对象时 出现以下错误 java lang IllegalStateException JSR 303 validated pr
  • 在同一父视图上多次使用一个局部视图

    我正在使用 MVC3 剃须刀 我有一个场景 我必须在同一个父视图上多次使用部分视图 我遇到的问题是 当渲染父视图时 它会在这些部分视图中生成相同的输入控件名称和 ID 由于我的部分视图绑定到不同的模型 因此当视图在 保存 上发回时 它会崩溃
  • 如何保护 ASP.NET Web API [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想建立一个RESTful使用 ASP NET Web API 的 Web 服务 第三方开发人员将使用该服务来访问我的应用程序的数据
  • 需要帮助理解这段代码

    我正在尝试学习单元测试 我正在尝试对我在 asp net mvc 1 0 中制作的一些会员资格内容进行单元测试 我一直在关注一本关于 MVC 的书 我对一些东西感到困惑 希望有人能为我解答 我的框架使用 Nunit 和 Moq 问题一 pu
  • 卸载 SSL 时保护表单身份验证 Cookie

    我正在尝试使用 ASP NET MVC 2 0 和表单身份验证来保护我当前正在开发的网站 为了保护表单身份验证cookie 我想将requiresSSL 属性设置为true 以便浏览器仅在连接处于SSL 下时才发送cookie 并且显然确保
  • 如何简单地检查服务器PHP版本是否为5或以上?

    我正在为程序创建预安装清单 该程序需要 PHP5 因此我需要检查列表脚本来检查 PHP5 的可用性 有一个函数为phpversion 将以以下格式返回5 3 6或类似的 然而 我希望清单非常简单 只是告诉你是或否 所以显示当前版本对我没有多
  • 如何添加没有值的属性

    我通过 html 助手和 TagBuilder 生成 HTML 文本框 我们有方法 TagBuilder Attributes Add key value 但对于 HTML5 required 属性不需要传递值 因此如果我传递空字符串 则输
  • 发布到列表 MVC3

    我试图让我的视图将列表发布回操作 但它始终为空 所以我的模型有一个 WeightEntry 对象列表 运动模型 public class Exercise public List
  • 最小有效 JSON 是多少?

    我仔细阅读了 JSON 描述http json org http json org 但我不确定我是否知道这个简单问题的答案 最小可能的有效 JSON 字符串是什么 string 该字符串是有效的 JSON 吗 42简单的数字是有效的 JSO
  • Web 文本编辑器中的 RTF 格式

    网络上是否有支持 RTF 格式文档输入的文本编辑器 我知道这对 webdev 来说有点奇怪 但我需要从数据库中读取 RTF 文档 并在基于 Web 的文本编辑器中对其进行编辑 然后将其存储回 RTF 中 在我在转换工具上投入太多资金之前 我
  • 在部分视图中传递参数 - MVC3/Razor

    如何将参数传递给 MVC3 razor 中的局部视图 我在 MVC 项目中用部分视图替换了常规视图页面 对于常规视图页面 我传递了如下参数 public ActionResult MeanQ int id Access access db
  • MVC DropDownListFor 和 StringLength 属性不能很好地协同工作

    我的字符串长度验证在具有字符串值的下拉列表上总是失败 这是我的模型 Required ErrorMessage Required StringLength 2 MinimumLength 2 Display Name Home Addres
  • 如何将 Ajax.BeginForm MVC 助手与 JSON 结果一起使用?

    我正在尝试使用 ASP NET MVC Ajax BeginForm 帮助程序 但不想在调用完成时使用现有的内容插入选项 相反 我想使用自定义 JavaScript 函数作为回调 这可行 但我想要的结果应该以 JSON 形式返回 不幸的是
  • 如何在类文件中使用 Url.Action() ?

    如何在 MVC 项目的类文件中使用 Url Action Like namespace 3harf public class myFunction public static void CheckUserAdminPanelPermissi
  • ASP.NET - 在表示层中显示业务层错误

    目前 在我正在开发的 ASP NET 应用程序中 基本验证 即必填字段 是在表示层中使用验证器和 ValidationSummary 完成的 这对我来说非常有用 因为 ValidationSummary 将显示多个错误消息 假设多个验证器设

随机推荐

  • 如何更改引导程序中面板的折叠方向

    我有一个众所周知的基本可折叠面板 其代码如下所述 我通过 css 设置更改了一些属性 例如折叠和折叠高度和宽度 但无法更改折叠方向 我想将其更改为与默认位置相反的顶部 我怎样才能做到这一点 我向你保证 我尝试了多种方法 但无法解决问题 di
  • 在 numpy 中加速矢量化眼球追踪算法

    我正在尝试实现 Fabian Timm 的眼球追踪算法 http www inb uni luebeck de publikationen pdfs TiBa11b pdf http www inb uni luebeck de publi
  • 如何读取 Perl 变量的根标签和根结束标签?

    我是 Perl 新手 我想将 xml 根标记和根结束标记读取到 perl 变量 我尝试了正常的文件读取 有效 我正在得到第一行和最后一行 但有时 如果没有新的线路 您就不能相信第一条线路 使用正则表达式读取第一行就完成了 但我在 googl
  • 为 go.mod 文件指定 Go 版本

    我正在通过 Heroku 部署应用程序 我愿意git push heroku master 我收到此错误 remote Compressing source files done remote Building source remote
  • Android 的 FragmentTabs 示例中的两个框架布局 Support4Demos

    我对 Android 中的片段不熟悉 我指的是为 supportv4 兼容性库提供的片段演示示例 谁能解释一下为什么有两种框架布局 android id realtabcontent android id tabcontent Androi
  • iPad Safari 视口的高度

    iPad 的视口宽度为 980 像素 高度是多少 在 Safari 中 我们必须添加地址和新的水龙头 Safari 横向模式下的高度是多少 有一个媒体查询可以使网页适合宽度 有没有办法使网页适合高度 以下是答案 你是对的 iPhone iP
  • PostgreSQL 权限授予不可见

    在 PostgreSQL 10 上 我有一个名为tn schema和一个名为tn beta db 我认为是的 尽管我确实必须连接到相关数据库才能查看架构 T jeff nantes 4 sudo su postgres c psql psq
  • lombok对jpa有副作用吗

    我正在努力将 jpa 实体转换为使用 lombok 结果代码如下 Entity Table name TEST Data NoArgsConstructor AllArgsConstructor class Test Column name
  • 如何在javascript中禁用输入文本框上的键盘事件

    我有一个图像 我使用键盘对其进行一些操作 翻译 缩放 在图像上方 我有一个输入文本框 显示数据集中图像的编号 当光标位于文本框上时如何禁用图像操作 即禁用我分配给每个键盘的行为 我还希望仍然能够编辑文本框 例如移动到图像编号 xx 从我在这
  • 如何在WPF中正确刷新自定义形状?

    我创建了一条自定义行 旁边有一些文本 形状是一个子类System Windows Shapes Shape 由于某种原因 当我更改线的坐标时 文本不会刷新 我知道关于InvalidateVisual 方法 但每次我移动元素时 我都必须调用它
  • Xcode 调试:查看 NSNumber 的值?

    是否可以在变量监视窗口中的调试器数据提示中看到 NSNumber 的数值 我在 NSNumber 中存储一个整数值 并希望在调试期间看到该值 我已经在调试器中尝试了一些数据格式化程序 但没有太大帮助 打开调试器视图并在摘要列中输入 int
  • 尝试在 python 中创建 virtualenv 并激活它

    我很难在 Python 中创建 virtualenv 并激活它 我正在研究Windows操作系统 在命令提示符下 我通过输入以下命令安装了 virtualenv pip install virtualenv 然后 为了在其中创建虚拟环境 我
  • 从 Javascript 中的对象列表中提取对象属性

    我从 API 接收到以下对象 2012 12 12 id 1234 type A id 1235 type A id 1236 type B 2012 12 13 id 1237 type A id 1238 type C id 1239
  • 需要一个策略将 Intellij IDEA 项目文件放入 Git 中

    需要一个将 Intellij IDEA 项目文件放入 Git 的策略 主要问题是如果idea项目文件在git中 如何避免分支之间的合并冲突 另一个问题是把它们保存在git中方便吗 如何避免合并 您可以保护某些文件不被合并合并管理器 http
  • SQL Server中的SQL group_concat函数[重复]

    这个问题在这里已经有答案了 如果有一张名为employee的表 EmpID EmpName 1 Mary 1 John 1 Sam 2 Alaina 2 Edward 我需要这种格式的结果 EmpID EmpName 1 Mary John
  • 如何使用 Alpaca 创建必需的条件字段?

    有谁知道如何定义依赖于另一个字段的必填字段 例如如果field1被标记true then field2必须为必填项 否则不应填写字段 2 这是我目前的尝试 field1 title Field1 type string enum true
  • Google Play 商店中的 Android 版本:选择加入 URL 在哪里?

    我正在努力在 Google Play 商店中发布我们的应用程序的私人内部版本 我收到一条消息 显示 当您发布应用程序时 此处将提供选择加入链接 但我不知道还需要做什么来发布我的 alpha 测试 apk 发布状态显示 全面推出 这向我表明一
  • 如何在 Windows 上为 python 3.7 正确设置 pyarrow

    我一直在尝试通过 pip 安装 pyarrow pip install pyarrow 并且 正如 Yagav 所建议的 py 3 7 m pip install user pyarrow 和康达 conda install c conda
  • UIControl 未接收触摸

    我有一个 UIControl 它实现了 Touchs Begin 方法 如下所示 void touchesBegan NSSet touches withEvent UIEvent event super touchesBegan touc
  • ASP.NET MVC 3 对嵌套对象的验证未按预期工作 - 验证子对象两次而不是父对象

    我正在尝试让 ASP NET MVC 3 从复杂的嵌套对象生成表单 我发现了一种意外的验证行为 我不确定这是否是 DefaultModelBinder 中的错误 如果我有两个对象 我们将 父对象 称为 OuterObject 并且它具有 I