views:

2360

answers:

3

Hi,

i am using ASP.NET MVC & ADO.NET Entity Framework in a project. I want to add validation logic to my entities via partial classes. It works similar like shown in the NerdDinner.com ASP.NET MVC Application which is using LINQ2SQL. The main difference is, that i have to use the"OnPropertyChanging" event instead the "OnValidating" like in LINQ2SQL.

There are some problems when doing it that way: - The "OnPropertyChanging" event is not the optimal point of calling validation logic, because it always triggers, even on creating a calling the default constructor. This really can cause serious problems (not only performance problems). - Together with the MVC framework there are problems when using the "EntityState.Detached" (i couldn't find any other way) to determine if a entity needs to be validated or not. Because a entity loses its entity sate during it gets displayed in the view (because on POST-event a new entity object is created instead of returning the original one).

My question is: Is there a better way of adding validation to ADO.NET Entities? I couldn't find any tutorials using a practical way of adding validation to ADO.NET Entities.

+1  A: 

Personally, I don't use the OnXChanging partial. You'd have to have another partial class for the entity that did something for that method signature.

I have one centralised save, (either by a helper method for that entity, or a save on a repository pattern implementation for that entity) where I validate the values meet my criteria before performing my context.SaveChanges().

Nor would I use the onpropertychanging event for validation, if I have a centralised save, then I only need to validate in one place, I would leave that for specific triggers at other points. (Like if user changed X then update Y)

DeletedAccount
OnXChangeing isn't an event you are right. But OnPropertyChanging is an event.
Alexander
Wow, never seen that before. I'll edit.
DeletedAccount
Yes OnPropertyChanged is a nice central event. But you still have the problem hat validation triggers unnecessary a lot of times. The EventState.Detached doesn't work with ASP.NET MVC because it gets lost...that's the reason why web applications are 'stateless' :-)
Alexander
Yes indeedy, that's why I'd use some sort of repository pattern to nicely detach to business objects / reattach to EF
DeletedAccount
+3  A: 

Personally, I don't put validation in the objects themselves. I use the xVal library to handle my entity validation.

xVal encourages you to annotate your entity classes (or, actually, metadata companion classes) with attributes that describe the various validation rules. These validation attributes are the default ones that come with .NET in System.ComponentModel.DataAnnotations.

You then run validation against your objects manually in your business layer. This is done by using a method that runs the System.ComponentModel.DataAnnotations validation logic. I wrote one that looks like this:

/// <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 provides a neat exception type you can throw that encapsulates validation errors and allows you to easily add them to the ModelState in your Controller.

xVal also will autogenerate client-side JavaScript form validation code for you by leveraging jQuery.Validate by providing an HtmlHelper method.

Check out http://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/ for a walkthrough on how it works. I've found it to be very nice way of doing validation that's not a total chore. It fits right in in the ASP.NET MVC way of doing things.

Daniel Chambers
A: 

One simple way to validate EF entity objects, is to use DataAnnotations on your model classes. There a two obvious benefit of this approach. One is that the same validation logic can be reused in many views such as edit and create. And the other is that when data annotations are available in our entity classes, ASP.NET MVC provides for implementing both client side and server side validation out of the box without much fixtures and coding.

This http://theminimalistdeveloper.com/2010/07/23/how-to-do-client-side-validation-in-asp-net-mvc-2/ shows in simple steps how this can be achieved in EF 4.0

Bikal Gurung