【问题标题】:Handling required fields in ASP.NET MVC when using Entity Framework使用实体框架时处理 ASP.NET MVC 中的必填字段
【发布时间】: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 应用程序中执行此操作可能要简单得多。
  • 不,我实际上并不熟悉。介意给我举个例子吗?
  • 检查this和this
  • 谢谢,我去看看。
  • 请注意,当您从视图(即作为控制器中的参数)接收使用域模型时,您可能会过度发布(除非您使用 Bind 属性)。 bradwilson.typepad.com/blog/2010/01/…

标签: c# asp.net-mvc entity-framework validation asp.net-mvc-3


【解决方案1】:

正如您所发现的,MVC 正在根据不可为空的类型验证您的模型。这会在您的自定义验证运行之前向 ModelState 添加错误。

我以前有过这种情况,并通过在动作开始时循环通过 Modelstate 并删除所有内容来解决它,然后进行我的自定义验证(不好!!)

然后发现即使你没有使用数据注解作为你的主要验证形式,你也可以通过在buddy类的不可空类型中添加[Required来自定义抛出的消息,并指定消息。

是这样的:

[MetadataType(typeof(YourClassMetadata))]
public partial class YourClass
{       
  //buddyclass to entity class
  class YourClassMetadata 
  {
    [Required(ErrorMessage="Your custom overriding error message")]
    public int NonNullablePropertyThatIsGivingYouProblems {get;set;}
  }
}

我已经开始研究 mvc 的流利验证 (http://fluentvalidation.codeplex.com),他们似乎通过添加行来关闭 global.asax 中的问题,在 application_start() 中

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

但我可能错了。

【讨论】:

  • 这正是我所需要的。我不知道如何使用元数据,以便可以对生成的实体进行简单的旧数据注释。谢谢!
【解决方案2】:

我知道这并不完全是您所问的,但是,我上周刚刚完成了一个项目,在该项目中我使用了 MVC 3 客户端验证和数据注释和不显眼的 javascript。它很拗口,但效果很好。您可以设置 regex、maxlenght、required 和所有其他属性,它会在客户端上对其进行验证。这使用户的表单验证速度更快。

这里有一些有用的示例链接,here、here 和一个非常好的 MSDN 示例供下载和试用 here

希望对你有帮助,

【讨论】:

  • 我实际上也在使用它。我真诚地希望您不只是验证客户端上的数据。有人要做的就是关闭javascript,他们会绕过你的所有验证。也就是说,我总是在我的项目中放弃 jquery.validate.js 和 jquery.validate.unobtrusive.js :) 我爱他们。
  • 感谢@Chevex 的精彩。继续进行服务器验证很重要。但就客户端而言,这些 def 摇滚!
猜你喜欢
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 2012-07-22
  • 2018-10-27
  • 1970-01-01
相关资源
最近更新 更多