【问题标题】:How to get model binder to leave null strings as null?如何让模型绑定器将空字符串保留为空?
【发布时间】:2009-07-09 16:48:42
【问题描述】:

My Sql Server 数据库有一些可以为空的 nvarchar 字段,并且没有包含空字符串的 nvarchar 字段。我想保持这种方式,但默认的 MVC 模型绑定器似乎将空字符串转换为空字符串。

当控制器检索到一个空的 nvarchar 数据库字段时,该空字段在控制器内部变成空字符串,然后视图从那里呈现它们,例如空白文本框。当页面发布时,默认模型绑定器使用这些空白文本框来更新模型,并且将以前的空字符串更改为空字符串。当数据更新回数据库时,空字符串会覆盖空值。

让模型绑定保持这些空值不变的最简单方法是什么?

【问题讨论】:

  • 什么是 SS 数据库,SQL Server?实际上,如果您测试 String.Empty 或 "" 而不是 null,您应该能够忽略差异,因为这两个东西也会为 null 返回 true。
  • 是的,SS = Sql Server。 Null 和空字符串不相同,无论是在 T-SQL 还是在 C# 中,您都不能忽略它们的区别。过去,我在一个项目中经历过痛苦的经历,其中两者的混合导致了很多意想不到的行为(错误)。例如,如果程序员刚刚测试 (x == null) 而不是在 C# 端使用 String.IsNullOrEmpty(x) 或在 SQL 中使用 (x IS NULL) 而不是 (x IS NULL OR LEN(x) = 0) 测试显然会随机失败,具体取决于 null 的默认值是否已更改为空字符串。
  • 今天又被这个咬了。我错过了用 [Required] 装饰类属性,所以我的验证器 (xVal) 没有注意到该属性变成了一个空字符串。然后将包含这个空字符串属性的对象写入数据库,其中表字段上的 NOT NULL 约束当然什么也没做。

标签: asp.net-mvc


【解决方案1】:

我知道您可能正在寻找更复杂的东西,但 ModelBinder 的默认行为是将空表单字段值转换为模型对象属性的数据类型的默认值。 String 属性变为空,int 属性变为 0,等等

您显然可以创建一个验证方案,该方案将在更新数据库之前检查 string.empty 并转换为 null。对于 int 表单字段,您需要检查 0,然后转换为 null。

【讨论】:

  • 感谢您的建议。我只关心字符串变为非空,而不是整数或其他任何东西。至于验证,我通过类注释和 xVal 项目来处理大部分工作。在此方案中,当检测到验证错误时,会抛出自动 RulesException 并自动转换为验证错误消息。我不想在实际上是由于模型绑定过程导致的页面上创建异常。
【解决方案2】:

这是我几个月前在找到 stackoverflow 的伊甸园之前使用的一个 hack。 :) 这很痛苦,而且不能很好地扩展,但它确实有效:

基本上,您会覆盖部分 linq 对象内部的绑定。如果您知道某个值应该始终为 null(但绝不是合法地为空),您可以执行以下操作。我将它用于基于字符串的用户 ID (SID)。

partial void OnSubProcess_Owner_UserChanged()
{
    if (string.IsNullOrEmpty(this.SubProcess_Owner_User))
       this._SubProcess_Owner_User = null;
}

詹姆斯

【讨论】:

    【解决方案3】:

    正确的答案可能是覆盖默认模型绑定器以自己添加此功能。

    也许您可以拥有一个 NullValueAttribute,您可以将其应用于字符串属性以识别空值。然后将空字符串设为空值。

    我现在遇到了同样的问题,可能会求助于这个

    【讨论】:

      【解决方案4】:

      我发布这个答案是为了解决这个问题。在使用它一段时间后,我开始将此问题视为模型完整性普遍关注的一部分。有一段时间,我已经在我的更新存储过程中实现了一个解决方案,以捕获空字符串并将它们转换为空值,就像上面 mikerennick 的回答一样。后来我还想确保字段被修剪,并且我碰巧将应用程序移动到 NHibernate(并且大部分存储过程都消失了)。最后,我嵌入了一些 POCO 逻辑来修剪和检查设置器中的空字符串(来自任何来源),如下所示:

      公共MyClass { 私有字符串_name; 公共字符串名称{ 得到 { 返回 _name; } 设置 { _name = value.TrimToNullIfEmpty(); } } } 公共静态类 StringExtensions { 公共静态字符串 TrimToNullIfEmpty(this string s) { 字符串 temp = (s ?? "").Trim(); 返回 temp.Length == 0 ?空:温度; } }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-02-09
        • 2021-10-18
        • 1970-01-01
        • 2014-08-24
        • 1970-01-01
        • 1970-01-01
        • 2014-09-10
        相关资源
        最近更新 更多