ASP.NET MVC中的最佳实践实体验证& ADO.NET实体框架

时间:2009-07-17 08:46:44

标签: .net asp.net-mvc entity-framework validation

我正在使用ASP.NET MVC&项目中的ADO.NET实体框架。我想通过部分类向我的实体添加验证逻辑。它的工作方式类似于NerdDinner.com ASP.NET MVC Application中使用的LINQ2SQL。主要区别在于,我必须使用“OnPropertyChanging”事件而不是LINQ2SQL中的“OnValidating”。

这样做会有一些问题: - “OnPropertyChanging”事件不是调用验证逻辑的最佳点,因为它总是触发,即使在创建调用默认构造函数时也是如此。这确实会导致严重的问题(不仅仅是性能问题)。 - 与MVC框架一起使用“EntityState.Detached”(我找不到任何其他方法)来确定是否需要验证实体时会出现问题。因为实体在视图中会丢失其实体状态(因为在POST事件中创建了一个新的实体对象而不是返回原始实体对象)。

我的问题是:有没有更好的方法为ADO.NET实体添加验证?我找不到任何使用向ADO.NET实体添加验证的实用方法的教程。

4 个答案:

答案 0 :(得分:4)

就个人而言,我没有在对象本身中进行验证。我使用xVal库来处理我的实体验证。

xVal鼓励您使用描述各种验证规则的属性来注释您的实体类(或实际上是元数据伴随类)。这些验证属性是System.ComponentModel.DataAnnotations中.NET附带的默认属性。

然后,您可以在业务层中手动对对象运行验证。这是通过使用运行System.ComponentModel.DataAnnotations验证逻辑的方法来完成的。我写了一个看起来像这样的人:

/// <summary>
/// Gets the validation errors for the passed in object by using reflection to retrieve the 
/// <see cref="ValidationAttribute"/>s placed on its properties or on the properties of the object's
/// metadata class (as specified by a <see cref="MetadataTypeAttribute"/> placed on the object's class)
/// </summary>
/// <param name="instance">The object to validate</param>
/// <returns>Any validation errors</returns>
/// <remarks>
/// Borrowed (and cleaned up) from
/// http://goneale.com/2009/03/04/using-metadatatype-attribute-with-aspnet-mvc-xval-validation-framework/
/// </remarks>
public static IEnumerable<ErrorInfo> Validate(object instance)
{
    //Try to get the MetadataType attribute from the object
    MetadataTypeAttribute metadataAttrib = instance.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().FirstOrDefault();

    //If the MetadataType attribute existed, get the metadata class
    //else just use the class of the object
    Type buddyClassOrModelClass = metadataAttrib != null ? metadataAttrib.MetadataClassType : instance.GetType();

    IEnumerable<PropertyDescriptor> buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass).Cast<PropertyDescriptor>();
    IEnumerable<PropertyDescriptor> modelClassProperties = TypeDescriptor.GetProperties(instance.GetType()).Cast<PropertyDescriptor>();

    //This query matches each property on the model class against the buddy class
    //gets a list of all invalid validation attributes and returns a list of
    //validation errors
    return from buddyProp in buddyClassProperties
           join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name
           from attribute in buddyProp.Attributes.OfType<ValidationAttribute>()
           where !attribute.IsValid(modelProp.GetValue(instance))
           select new ErrorInfo(buddyProp.Name, attribute.FormatErrorMessage(String.Empty), instance);
}

xVal提供了一个可以抛出的简洁异常类型,它封装了验证错误,并允许您轻松地将它们添加到Controller中的ModelState中。

xVal还将通过提供HtmlHelper方法利用jQuery.Validate为您自动生成客户端JavaScript表单验证代码。

查看http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/了解其工作原理。我发现这是一种非常好的验证方式,这不是一项繁琐的工作。它适合ASP.NET MVC的工作方式。

答案 1 :(得分:1)

就个人而言,我不使用OnXChanging部分。您必须为该方法签名执行某些操作的实体设置另一个部分类。

我有一个集中保存(通过该实体的帮助方法,或者保存该实体的存储库模式实现),在执行context.SaveChanges()之前我验证了值符合我的条件。

我也不会使用onpropertychanging事件进行验证,如果我有一个集中保存,那么我只需要在一个地方进行验证,我会将其留给其他点的特定触发器。 (如果用户更改了X,则更新Y)

答案 2 :(得分:0)

验证EF实体对象的一种简单方法是在模型类上使用DataAnnotations。这种方法有两个明显的好处。一个是可以在许多视图中重用相同的验证逻辑,例如编辑和创建。另一个是当我们的实体类中有数据注释时,ASP.NET MVC提供了开箱即用的客户端和服务器端验证,而没有太多的夹具和编码。

这个http://theminimalistdeveloper.com/2010/07/23/how-to-do-client-side-validation-in-asp-net-mvc-2/以简单的步骤显示了如何在EF 4.0中实现这一目标

答案 3 :(得分:0)

您是否已查看过IValidatableObject实现。我不确定这是否能回答你的问题;但是,使用此功能,您的验证将保留在您的域对象中。

更多关于它的例子是: How do I use IValidatableObject?

DataAnnotations用于运行正常验证;但是,如果存在复杂的验证,则可以创建自己的ValidationAttribute或实现IValidatableObject。如果你走这条路,你可以使用两者的组合。我通常这样做。