Business Validation side by side with DataAnnotations in layers - asp.net-mvc

I have a MVC 3 application with a 3 layer approach. My Data layer contains the edmx file and a t4 template which generates my entities with the basic DataAnnotations every time my edmx file changes.
In addition I am making use of following to allow additional validation for existing entity and property. This one allows me to combine the auto generation DataAnnotations with own written annotations.
[MetadataType(typeof (PersonMetaData))]
public partial class Person
{
}
public class PersonMetaData
{
[RegularExpression(#"(\w|\.)+#(\w|\.)+", ErrorMessage = "Email is invalid")] public string Name;
}
Going further I found following article http://www.howmvcworks.net/OnModelsAndViewModels/ExtendingTheModelBinderForEnhancedValidation
This allows me to use the existing ASP.NET MVC logic and implement, if needed, an own validation method. The example works for me.
Unfortunately, because I have a 3 layer application and want to validate my entities in the Business logic (and not in the Data layer), I cannot put any call to the Business Logic into the Validate method without creating a circular dependency.
Is there any better approach to combine auto generated DataAnnotations, own validationextensions, validation in the business logic and the IBindingValidatable method?
Thank you

You should keep validation resulting from business logic rules in the business layer, and only include data entry validation in the UI layer.
So for example validating an email address entry, according to some regex belongs in the UI layer, but making sure that email address is unique to your system should be done in the business logic.
I hope this helps.

Related

FluentValidation usage in AspNetMvc n-tier project

I have a multi-layered project. Layers are as follows :
Business
DataAccess
Entities
Core
MvcWebUI
I have a Category class in entity layer:
public class Category : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
I also have a CategoryValidator class in the business layer:
public class CategoryValidator : AbstractValidator<Category>
{
public CategoryValidator(IEnumerable<Category> categories)
{
RuleFor(x => x.Name).NotEmpty().MaximumLength(50);
}
}
I have a class in the Core layer for validation.
public class ValidatorTool
{
public static void FluentValidate(IValidator validator, object entity)
{
var result = validator.Validate(entity);
if (result.Errors.Any())
throw new ValidationException(result.Errors);
}
}
I'm performing validation in the Business layer with the FluentValidate method.
But I got stuck when it came to the MvcWebUI layer. According to the FluentValidation documentation, I need to apply an attribute to the entity class as follows:
[Validator(typeof(PersonValidator))]
But since the business layer references the entity layer, I can't reach the CategoryValidator class in the entity layer. (circle reference)
How can I solve this problem?
Did I create the layers incorrectly?
Or should I define the entities as a model again in the Web layer?
Please help me.
Firstly, you probably shouldn't be exposing your entities directly in the UI so I'm going to recommend you create new models there and write validators specifically for them.
Assuming this is wired up correctly, this approach means the validators are automatically fired during the HTTP POST in the MVC app and the model state is automatically updated with a list of errors.
I use this approach extensively, albeit in MVC apps that call an internal API.
In the majority of my cases, the MVC client validates the model and if it passes the checks it then calls the API or service layer after with a DTO / service / entity model which is mapped with Automapper.
The MVC validation is typically light and checks for required fields, lengths, etc.
The API does validation again but it does it on the entity and it goes much deeper this time as it checks for duplicates, invalid entity state, etc. .
One last comment that I would like to add. I wouldn't throw exceptions on validation errors. The UI should use ModelState and the service layer returns a result which the client knows how to merge back into ModelState so either scenario results in the users getting a nice list of errors to deal with.
Hope this helps!
Generally you have 2 ways to perform validation:
Validate View Models (used in most cases)
Internal Business Entities validation (which most often used with 1-st)
For 1-st point you validate view models (on client and server), which placed in your Web project. In that case you should place view model validators in Web project too. [Validator(typeof(PersonValidator))] attribute is needed for linking view model parameter of action and action itself to perform validation before action execution. As in documentation:
Internally, FluentValidation’s MVC integration makes use of a validator factory to know how to work out which validator should be used to validate a particular type. By default, FluentValidation ships with an AttributedValidatorFactory that allows you to link a validator to the type that it validates by decorating the class to validate with an attribute that identifies its corresponding validator.
If you want to validate business models (2-nd point), not/not only view models, you need to place entity validators to Business project and register them in your IoC container (example with Castle Windsor), and change validator tool next way:
public class ValidatorTool
{
public static void FluentValidate<T>(IContainer container, T entity) // replace IContainer with your actual container interface name
{
var validator = container.Resolve<IValidator<T>>();
var result = validator.Validate(entity);
if (result.Errors.Any())
throw new ValidationException(result.Errors);
}
}

Griffin localization and Fluent Validation

I am new to Griffin localization, it seems very cool. However, examples are only showing me how to translate MVC validation attributes.
I am using minimum if not none of the mvc validation attributes. My idea is (try) not to validate and report messages twice at data layer and UI layer. I create validators at data layer with with Fluent Validation.
Could you please give me a quick pointer (if it exists) how we can integrate Griffin Localization with Fluent Validation at data layer?
Griffin.MvcContrib do not have any support for Fluent Validation.
Just took a quick look at fluent validation and it seems like it pulls its string from IStringSource. So you could basically create an adapter for it which reads the strings from the Griffin.MvcContrib resources.
Something like:
public class FluentValidationTranslator : IStringSource
{
public FluentValidationTranslator(ILocalizedStringProvider griffinProvider)
{
}
// implement the translation here
}

Code first: does fluent api influence UI?

I'm reading a book written by Julie Lerman on Code First. According to the book, annotations and fluent api give the same result. Everything depends on the style of the developer.
I know that annotations allow both to configure how code first generate database objects and how MVC customize UI elements. Let's say I use [Required, MaxLength(50)]. The attribute will generate a NOT NULL, nvarchar (50) in the database. It also will validate the input for that field.
[Required, MaxLength(50)]
public string Name { get; set; }
What if I decide to use Fluent API to configure Code first. Am I still going to need annotations to influence UI elements or using fluent API is going to be enough?
EDIT
How about annotations, such as Display that serve only for UI purposes? Do they have equivalents? If not, Will I need to use annotaions?
[Display(Name = "Date of Birth")]
public DateTime BirthDate { get; set; }
Thanks for helping
Data Annotation is the simplest way of telling a class to enforce some validation rule. You can do the same thing with Fluent API as well. Some people like doing it by data annotations and some people like it by doing with fluent API
Reasons to like it with Data Annotations
1) Keep the validation info about my entity in one place along with the entity definition
Reasons to like it with Fluent API
1) Keep my entity clean. It will have only my property info. No validation info. Clean and simple POCO. I will write validation on the OnModelCreating method in my data context class.
You can not do all Fluent API things with Data Annotations way. the same way you don't have few Data Annotations attributes equivalant not present with Fluent API way ( Ex : HasMinLength) . HasMinLength is something we will for our Model validation which usually makes sense in the UI.
For the UI Model Validation, you can not use the Fluent API alone. Fluent API's major role is to look into the fluent configuration we writes and act when creating the Model(Database) from the entities. Remember we are overriding the OnModelCreating method to write our fluent API configuration. So for the UI Validation (of my ViewModel), I would use the DataAnnotation way and use fluent API if i want to define some thing related to my datamodel like Define a foreign key or Map this Entity to a Table with different name etc..
EDIT : As per the question edit,
You should make use of the Data Annotations in this case. If you are doing code first. You may remember that that entity is going to be your Database table ( of course you can tell EF to ignore /rename specific columns). In that case, I would keep my Entities clean and Create a ViewModel which i will use in my UI. I will add my DataAnnotations in my ViewModel to handle it. I may write some mapping code which maps data from ViewModel to Model and Model to ViewModel wherever necessary.
If your entity model classes are doubling as your viewmodel classes, AND you are using the default out of the box DataAnnotationsValidationProvider, then you would need the dataannotations attributes on the model properties to get validation.
However, you should not double your entity classes as viewmodel classes. Take for instance, a controller that needs to have a ReturnUrl property in its model. You wouldn't want this in your entity model / database. Because of differences like this between the View model and the Entity model, the 2 should really be separate (yet cohesive) layers in your application. You can make them cohesive using a library like AutoMapper.
This is one of the reasons I prefer the fluent API. If you stick to the fluent API, then you would never put any attributes on any entity model classes or properties. When it comes time to show, insert, or update data, you put the attributes on the viewmodel classes only.
Also, the [Required] attribute on an entity type performs validation during SaveChanges, whereas a [Required] attribute on a viewmodel performs validation during model binding.
According to Julie Lerman's book on DbContext, you do NOT need any additional annotations to your Fluent API configuration. The Name property will get validated by Validation API as if it had been configured with Data Annotations.
According to the same book, MaxLength and Required are the only validation attributes with fluent API conterparts.

DRY Validation with MVC2

I'm trying to figure out how I can define validation rules for my domain objects in one single location within my application but have run in to a snag...
Some background: My application has several parts:
- Database
- DAL
- Business Logic Layer
- SOAP API Layer
- MVC website
The MVC website accesses the database via the SOAP API, just as third parties would. We are using server and and client side validation on the MVC website as well as in the SOAP API Layer.
To avoid having to manually write client side validation we are implementing strongly typed views in conjunction with the Html.TextBoxFor and Html.ValidationMessageFor HTML helpers, as shown in Step 3 here. We also create custom models for each form where one form takes input for multiple domain objects.
This is where the problem begins, the HTML helpers read from the model for the data annotation validation attributes. In most cases our forms deal with multiple domain objects and you can't specify more than one type in the <%#Page ... Inherits="System.Web.Mvc.ViewPage<MvcApplication.Models.SomeModel>" %> page directive. So we are forced to create a custom model class, which would mean duplicating validation attributes from the domain objects on to the model class.
I've spent quite some time looking for workarounds to this, such has referencing the same MetadataType from both the domain class and the custom MVC models, but that won't work for several reasons:
You can only specify one MetadataType attribute per class, so its a problem if a model references multiple domain objects, each with their own metadata type.
The data annotation validation code throws an exception if the model class doesn't contain a property that is specified in the referenced MetadataType which is a problem with the model only deals with a subset of the properties for a given domain object.
I've looked at other solutions as well but to no avail. If anyone has any ideas on how to achieve a single source for validation logic that would work across MVC client and server side validation functionality and other locations (such as my SOAP API) I would love to hear it!
Thanks in advance,
Matthew
What you should do is instead of trying to replicate the structure in the view models, use your existing models in the data model classes.
When you bind the form data back to the view model, you can restrict which columns will be bound back using the [Bind] attribute on the parameter. Or use any other approaches to do this.
So if your model creates classes like Product User and Category, and your view model needs to use some of their properties, create a view model like this:
public class PageViewModel
{
public Product Product { get; set; }
public Category Category { get; set; }
public User User { get; set; }
}
In your page you will be able to use them with
<%: Html.EditorFor(m => m.Product.ProductName) %>
In this case the validation attributes from your actual classes will be used, as required.
Does that give you an acceptable solution?
How about returning a container class that has nested types in your action method?
http://weblogs.asp.net/blogs/rajbk/image_63B7D5D4.png

Does ASP.Net MVC 2 validation need some more thought in terms of patterns and use?

Here is the lay of the land. Like most people I have my domain object and I have my view models. I love the idea of using view models, as it allows for models to be created specifically for a given view context, without needing to alter my business objects.
The problem I have is with type level validation defined on my domain object and getting those rules to the client. In this case lets say I am using data annotations to describe the validation rules, when I move the data from the domain object to the view model, the view model no longer knows what validation it should get the interface to perform (because the validation is defined back on the domain object).
With MVC 2 you can get it to automatically perform client/server side validation, based on the validation rules of the current object. But because the validation rules are defined on the domain object and not the view model, I would have to duplicate the validation rules on the view model to get this to work.
How do others deal with this type of issue? My thinking is that besides mapping the data from the domain object to the view model, we also need to map across the validation rules, but I haven't really seen others talking about this issue... Brad Wilson has recently talked about this issue at length but hasn't really addressed the duplication of rules on the domain object and on the view models... what are your thoughts?
Cheers
Anthony
The DataAnnotation attributes are about validating input and giving UI feedback to the end user. That's really their only intended use. I use different validation strategies for UI objects and business objects, so the DA validation attributes only end up on models being shown to the user.
This may not be appropriate, but what if you just moved your validation rules/annotations from your Models to your ViewModels? In a few of the projects I've been on, we've chosen to prevent the View from accessing anything but information exposed through its corresponding ViewModel. Since all data interaction would be performed through the ViewModel, there wouldn't be a need to have validation on your Model objects.
The counter to this argument is that you could easily duplicate certain validation rules, since different ViewModels might be interfacing with the same Models. In this case, it might make sense to simply declare your Model as a property exposed on your ViewModel. For postbacks, they could accept a Model as their parameter, allowing the ModelBinder infrastructure to handle the request. In this case, if ModelState.IsValid is false, you could just reassign the property to your ViewModel before redisplaying the View.
I would recommend moving your annotations to your ViewModels. It makes sense since a lot of Views are a) the result of composition of several models or b) a subset of model data.
It turns out that AutoMapper may be able to do this for us automagically, which is the best case scenario.
AutoMapper-users: Transfer validation attributes to the viewmodel?
http://groups.google.com/group/automapper-users/browse_thread/thread/efa1d551e498311c/db4e7f6c93a77302?lnk=gst&q=validation#db4e7f6c93a77302
I haven't got around to trying out the proposed solutions there, but intend to shortly.
(Cross posted this on my (dupe) question as well).
Probably we shouldn't use view models at all?
And define validation rules on model layer entities..
I've been considering this as well for a while now. I totally understand Brad's reply. However, let's assume I want to use another validation framework that is suitable for annotating both domain entities and view models.
The only solution I can come up with on paper that still works with attributes would be to create another attribute that "points" to a domain entity's property that you are mirroring in your view model. Here's an example:
// In UI as a view model.
public class UserRegistration {
[ValidationDependency<Person>(x => x.FirstName)]
public string FirstName { get; set; }
[ValidationDependency<Person>(x => x.LastName)]
public string LastName { get; set; }
[ValidationDependency<Membership>(x => x.Username)]
public string Username { get; set; }
[ValidationDependency<Membership>(x => x.Password)]
public string Password { get; set; }
}
A framework like xVal could possibly be extended to handle this new attribute and run the validation attributes on the dependency class' property, but with your view model's property value. I just haven't had time to flesh this out more.
Any thoughts?

Resources