Custom validation with Data annotations

asp.net-mvc data-annotations entity-framework

Question

I'm using data annotations to check data that's being entered, but I'm stuck when it comes to more custom way to validate data.

I need to run queries against database to see if stuff exists there or not, and then report back to user if a "custom db-check error" appears, such as "The Companyname already exists"

How can I implement such a thing together with dataannotations?

I have all the queries done etc using linq and entity framework that comes with 3.5sp1

/M

Accepted Answer

Custom attributes that extend data annotations

You will have to write your own attributes that will do the validation of your object instance against data store.

Make sure your classes inherit System.ComponentModel.DataAnnotations.ValidationAttribute class:

public class MustNotExist: ValidationAttribute
{
    ...
}

Caution

I've run into a similar situation when I needed to validate that the object is unique within data store. But this kind of validation wasn't possible on the entity class itself, since it should only work for those entities that are being created but not when you return your entity from the data store already.

My solution was to have a separate interface, class and attribute.

public interface IExternalValidator ...

class DBUniqueValidator: IExternalValidator ...

class ValidateExternallyAttribute: FilterAttribute, IActionFilter
{
    ...
    public ValidateExternallyAttribute(Type validatorType, Type entityType) ...
    ...
}

I was able to place my attribute on controller actions that get entity parameters. Filter action attribute then checks controller action parameters (it can easily access their types and values) and runs external validator against correct parameters (provided types in attribute definition) and populates ModelState errors when validation fails.

[ValidateExternally(typeof(DBUniqueValidator), typeof(User))]
public ActionResult RegisterUser(User newUser)
{
    if (!this.ModelState.IsValid)
    {
        // act accordingly - probably return some error depending on model state errors
    }
    // register new user in data store
}

This way I was able to run external validation only on those actions that actually needed it, and this technique also helped my controller actions code to stay clean and short. All I had to do is to check if there are any model state errors.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why