Entity Framework: Where to put business logic that that ASP.NET ModelState is populated? - asp.net-mvc

I have a site that uses Entity Framework for data persistence.
I have used the buddy class system on a number of Entities to flag what fields are required using data annotations.
ASP.NET MVC and its ModelState work great with this out of the box.
My question is, I have some validation that is a little more involved -
Is there a way I can include this business logic in the buddy class in such a way that the ModelState is populated correctly?
An example of this would be
If field X is of one value, then Field Y is required.
The logic may get more complex than this.
Thanks,

This could be achieved by writing custom validator attributes. But personally I prefer the FluentValidation.NET framework instead of data annotations as it provides a more concise and easier way to express custom validation logic even in complex scenarios.

You should make the entities themselves implement IValidatableObject, then use an iterator to yield return a ValidationResult for each error.
Alternatively, you can make a custom class-level ValidationAttribute and apply it to the buddy class.

Related

Is it okay to use attributes and IValidatableObject on domain objects?

I am used to working with entity objects and now I am switching to DDD principles so I will start using domain objects.
I am used to decorate the properties of my entity objects with attributes such as RequiredAttribute or StringLengthAttribute. I am also used to implement the IValidatableObject on my entity objects.
My question is - is it acceptable to use attributes and IValidatableObject on my domain objects? Is it consistent with DDD? Thank you.
Your domain model should work only with business concepts, it shouldn't have any direct relations to DAL or View. Attributes you have applied means that you use your domain model as view model. Create separate viewmodel. Don't use your entity objects which describing your storage model as root class for your domain.Create new classes for your domain objects. Add methods which clear explain business -
ChangeLastName(string newName) instead of obj.LastName = "Some name"
CreateNewPost(string text,string author) instead of obj.Posts.Add(..)
You can write some extension methods to make mappings, like ToViewModel, or do it some else.One interesting design/infrastructure pattern is CQRS & EventSourcing. It allows you avoid mappings, but have some drawbacks (like transactions between aggregates). And last - in most cases simple CRUD operations more suited - fast, simple, easy.
From a DDD point of view, the domain model is best kept lean with the use of exceptions in your entity’s behavior methods, or by implementing the Specification and Notification patterns to enforce validation rules.
It can make sense to use data annotations at the application layer in ViewModel classes (instead of domain entities) that will accept input, to allow for model validation within the UI layer. However, this should not be done at the exclusion of validation within the domain model.

Use data annonations in ASP.NET MVC using DDD

I've started to develop ASP.NET MVC application using Entity Framework and I wish to use DDD. It's my first time using DDD in ASP.NET (used until now in PHP), so I'm little confused.
I'm using code-first approach, so I'm creating my entites in the core and then the DbContext in the Infrastructure.
My questions is about data annotations: Is it OK to annonate the entities in the core? with Required, DataType, etc. or I have to create entries with pure C# validation (in the setters and getters) and then create a map objects for the database creation?
For example, I got:
public class Account
{
public string AccountName { get; set; }
}
Can I annonate the AccountName with [Required] or I need to create a map class which will just reflect the exact same properties in the Account class but will have attributes and that will be the class that I'll use in Entity Framework DbContext?
Thanks!
Neither.
Your entities should have barely any public getters or setters. Domain model is a behavioral model, not a data model. Your entities should have private fields and methods that changes the entity state. Those methods should have a business meaning and should protect entities invariants (validate input). For example - we have UserAddress and want to change it. Is it just user.Address = newAddress? NO. What's the meaning of changing that? Maybe your User want to FixMistypedAddress(str). Or maybe your UserMoved(newLocation)? Different business rules may apply tho those scenarios. For example when UserMoved() we want to send him a champagne bottle, but not when he just fixed a typo. You should already see that there is no use of data annotations here because we don't just set properties but we do meaningful operations.
Entities should always be valid. That mean there should be no way to put it in an invalid state. Data annotations only allow you to check whether the object is valid or not. They not guarantee is will be valid all the time.
IMO Data annotations are fine for:
Using Entity Framework in a CRUD application (no DDD applied)
In DTO or ViewModels. In other words - for validating user forms, not entities.
So the first quiestion for you is: Are you doing CRUD or DDD?
I'd say either way is fine.
If you want a more pure approach you would create a buddy class that has the metadata on it however it is also acceptable to put it directly on the domain class.
In the end it comes down to how much you want to remain "pure" and how much extra work you want to put into maintaining buddy classes, not to say that it is a bad thing.

What advantage has Fluent Validation vs the default .NET Data Annotations

What advantage does the FluentValidation library have over the .NET System.ComponentModel.DataAnnotations?
Does it offer more flexible validation as it is not annotated (static field validation) on the property like validating a property depending on another's property value?
I'm not sure about data annotations but we've used FluentValidation for validation part in business logic. And easy integrating with ASP.NET MVC is nice bonus :)
It supports a lot of built-in rules, error messages localization, using object data in error messages, custom validation methods, conditional validation - applying some rules if object data matches a condition, rule sets - apply named set of rules, validation of aggregated objects and collections - and property names would be compatible with ASP.NET MVC property names and so on.

MVC3 EF model-first with POCO and ViewModels

Lots of great posts out here on this topic and I've tried to read them all. I'm a long time n-tier developer but trying to swing into action with an MVC3/EF application. I've generated POCOs via the EF POCO generator(T4). I'm also binding ViewModels to my Views...no EF stuff in my Views. My question has to do with validation (U/I only). I like the idea of DataAnnotations and want to use them. However, to use them correctly I have to use them in my ViewModels. From the advice I see on this site and others, I'll have to replicate any properties from my POCOs into my view models and do my annotations there. To make this easier I've seen lots of suggestions to use AutoMapper to make this tedious mapping more bearable.
Do I pretty much have the right idea?
I'm also binding ViewModels to my Views...no EF stuff in my Views
Correct. Ideally, your POCO's should not be on your Views.
I like the idea of DataAnnotations and want to use them. However, to use them correctly I have to use them in my ViewModels
Correct. There shouldn't be any data annotations on your POCO's.
From the advice I see on this site and others, I'll have to replicate any properties from my POCOs into my view models and do my annotations there
Why? Are you always binding to all of the properties on your POCO's? Remember, the ViewModel is to serve the View only. So if you have a form to submit an order, the ViewModel should only contain what is required to persist that Order. A combination of AutoMapper and your custom code can then map that to your POCO.
To make this easier I've seen lots of suggestions to use AutoMapper to make this tedious mapping more bearable
#Craig is right, it has nothing to do with Data Annotations. AutoMapper maps your ViewModel to your domain models with a few lines of configuration.
AutoMapper is only about transformation from entity to view model and vice versa. It is just replacement of code like custom conversion operator between types. You will still have to create your view models and mark properties with correct data annotations.

Combine DataAnnotations Validation with complex business rules

I understand annotating class properties with the basic required and minimum length and getting all the benefits of the asp.net mvc server side and client side validation.
However does anyone have a link that shows how you combine this 'base' validation with more complex business rules. How would I run business rule functions, such as for example, has the customer ordered anything in the last year (database hit required) and still use the same DataAnnotation and mvc validation plumbing?
Goal : Don't want two ways of generating and outputting validation methods.
From http://msdn.microsoft.com/en-us/library/dd901590%28VS.95%29.aspx:
To create customized validation checks, you can either create a class that derives from the ValidationAttribute class or create a method that performs the validation check and reference that method when applying the CustomValidationAttribute to the data member. When you create a class that derives from ValidationAttribute, override the IsValid method to provide the logic for your customized validation check.
There appears to be example code there.
Data Annotation run before your action is invoked. Then, regardless whether the validation succeded or not, the action is still called. If the DA detected invalid data, your ModelState will be invalid.
Once here, you can still do any validation you want, for your business rules, as you would normally do without the data annotation, if you want to. In your action, you can add errors to the ModelState even if the Data Annotation validation passed.
In this case, you add your errors with ModelState.addError, and those errors are added to any error provided by the DA. So in your View it doesn't matter where the error comes from.
Or, if your rules are general, you can write your own annotation tags. The Data Annotation thing is distributed with its source, so you have full control on it.
You could use VAB (Application Validation Block) from the Enterprise Library 5 of Microsoft that actually based on the DataAnnotations class but u do your complex bussiness logic very easily through configuration...
i'd suggest you check it out...
Have a look at following article, where you can use DataAnnotations Multiple Times On Same Field, Compare N number of properties and N number of values....
http://www.codeproject.com/KB/validation/MultipleDataAnnotations.aspx

Resources