【发布时间】:2011-07-18 11:40:29
【问题描述】:
让我先一步一步描述我的应用程序。
首先我有我的实体框架生成的模型。在其中我有以下实体:
http://www.codetunnel.com/EFEntities.jpg
现在,为了在实体上实现验证,我使用部分类并处理 EF 提供的 OnChanging 挂钩。这是PostComment 部分类的示例:
namespace CodeTunnel.Domain.Models
{
public partial class PostComment : IDataErrorInfo
{
private Dictionary<string, string> _errors = new Dictionary<string, string>();
partial void OnAuthorChanging(string value)
{
//Validating anything but required value works fine.
//Like this pseudo-validator.
if (value.ToLower() != "fred")
_errors.Add("Author", "Sorry, your name must be Fred.");
}
partial void OnBodyChanging(string value)
{
//Required value validation does not work, I will tell you why below.
if (string.IsNullOrEmpty(value))
_errors.Add("Body", "Body is required.");
}
#region -= IDataErrorInfo methods =-
public string Error
{
get { return string.Empty; }
}
public string this[string columnName]
{
get
{
if (_errors.ContainsKey(columnName))
return _errors[columnName];
return string.Empty;
}
}
#endregion
}
}
请注意,我的类继承自 IDataErrorInfo。默认情况下,MVC 会检查此验证错误。如果发现任何错误,则使模型无效,并将存储的错误用作视图中验证助手的消息。我很确定当 EF 抛出异常时,这个字典甚至不会填充该属性的值。事实上,我什至不确定 MVC 是否会在检测到模型并在 EF 生成的异常时使模型无效后寻找一个值。
这是问题的屏幕截图,包括示例伪验证器,因此您可以看到它正在工作:
http://www.codetunnel.com/ValidationError.jpg
如您所见,错误消息没有出现。但是,它确实正确地验证了该字段为无效。如果我在那里输入一个值,那么它的验证就很好。我已经对这个问题进行了大量研究,以下是我所知道的:
您无法自定义为必填字段显示的错误消息的原因是模型属性不可为空。因为它不可为空,所以尝试将空值绑定到它会引发异常。 MVC 会吞下这个异常,并按应有的方式使模型无效。发生此异常的任何地方都会生成该消息。我不知道消息是由 EF 还是 MVC 生成的(我猜是 MVC,因为它首先负责吞下异常)。我不知道如何自定义此消息。如您所见,它总是说“值''无效。”我认为这并不完全可怕,但它确实不是非常用户友好。
它会进入我的姓名验证器并检查您的姓名是否是“fred”,因为没有引发异常。就 EF 而言,传入的值很好。直到它到达我的OnAuthorChanging 方法时,它才意识到这不好。这是正确的行为,并且工作正常。
如果我在 OnChanging 事件中抛出异常而不是添加到我的 IDataErrorInfo 字典中,我可以生成相同的验证消息,只是它将输入的值放在单引号之间。示例:
partial void OnAuthorChanging(string value)
{
if (value.ToLower() != "fred")
//_errors.Add("Author", "Sorry, your name must be Fred.");
throw new Exception("Sorry, your name must be Fred.");
}
当输入“test”作为 Author 的值时,该代码会显示此消息:“值 'test' 无效。”。对于必填字段,只是值为 null,因此单引号之间没有任何内容。
有几个人 (like this guy) 建议您只需在模型中将该属性设置为可为空即可。这不是一个可接受的解决方案。原因之一是:
错误 3031:映射问题 从行开始的片段 313:不可为空的列 PostComments.Body in table PostComments 被映射到一个可为空的 实体属性。
此外,设置 nullable 根本不适用于 int 等不可为 null 的类型,并且将 int 切换为可为 null 的 int 是一团糟,我什至不会在这里讨论。
底线是,我想自己处理来自 EF 的那些异常,或者至少自定义它生成的消息,但我不知道如何。我完全迷路了。我想做的就是自定义一条关于我认为非常简单的模型验证的消息!
【问题讨论】:
-
除此之外,您还使用 MetaDataType 属性(伙伴类)吗?如果没有,在 MVC 应用程序中执行此操作可能要简单得多。
-
不,我实际上并不熟悉。介意给我举个例子吗?
-
谢谢,我去看看。
-
请注意,当您从视图(即作为控制器中的参数)接收使用域模型时,您可能会过度发布(除非您使用 Bind 属性)。 bradwilson.typepad.com/blog/2010/01/…
标签: c# asp.net-mvc entity-framework validation asp.net-mvc-3