Griffin localization and Fluent Validation - asp.net-mvc

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
}

Related

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.

Business Validation side by side with DataAnnotations in layers

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.

Testing model validation without testing implementation

What's the best way of going about testing model validation without making assumptions on the implementation details of the validation (eg. DataAnnotations).
For example, if I have a Customer model object that has a Firstname property, I want to test that binding a missing value for the Firstname property will result in a validation error but I don't want to test how validation his been implemented. That is, I don't want to use DataAnotations.Validate.
I've seen several, differing, opinions on this floating around and haven't found one that I agree with.
I ended up writing a helper method that wraps ModelValidator and returns IEnumerable<ModelValidationResult>. It requires that MVC be configured with your validation provider of choice, but it means that test code need not change when your validation implementation does:
public static IEnumerable<ModelValidationResult> Validate<TModel>(TModel model)
{
var modelMetadata = ModelMetadata.FromLambdaExpression(r => r,
new ViewDataDictionary<TModel>(model));
ModelValidator validator = ModelValidator.GetModelValidator(
modelMetadata, new ControllerContext());
return validator.Validate(model);
}
This will depend on the framework you are using for validating your models. So what you are asking is not possible without taking this into account. ASP.NET MVC by default uses a data annotations model provider which invokes the validation rules for data annotations and if you want to test this you will need to do a DataAnnotations.Validate in your unit tests or verify that your model is decorated with the proper attributes.
Personally I use FluentValidation.NET which provides an elegant way for unit testing my validators so it is not much of a hassle.

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

ASP.NET MVC: Is Data Annotation Validation Enough?

I'm using the Data Annotation validation extensively in ASP.NET MVC 2. This new feature has been a huge time saver, as I'm now able to define both client-side validation and server-side validation in one place. However, while I was doing some detailed testing, I realized that it's quite easy for someone to bypass the server-side validation if I relied on Data Annotation validation alone. For example, if I defined a required field by annotating the property with the [Required] attribute and placed a textbox for that required field in a form, a user could simply remove the textbox from the DOM (which can easily be done through Firebug) and now the Data Annotation validation will not be triggered on that property during ModelBinding inside of a Controller. To ensure that the "required" validation is triggered, I can repeat the validation after ModelBinding happens, but then I'd be repeating my validation logic.
What is everyone's recommendation on validation? Is Data Annotation validation enough? Or does the validation need to be repeated to ensure that validations get triggered in all situations?
Follow-up comment:
Based on the answers below, it seems that I can't rely on the Model Binder and Data Annotation validation alone. Since we're concluding that additional server-side validation is required, is there an easy way for my Service layer to trigger validation based on what's been defined in the Data Annotations? It seems that this will get us the best of both words...we won't need to repeat the validation code, but we'll still ensure that the validation gets executed even if Model Binder doesn't trigger it.
I'm going to post this follow-up comment as a separate question, as it poses a different question than the original one.
I think to be vigilant concerning security you should choose to you make server validation the priority and ensure that this is always your fallback. Your server validation should work without the client validation. Client validation is more for UX and tho that is paramount to your design, it is secondary to security. With this in mind you will find yourself repeating your validation. A goal is often trying to design your app so that the server and client validation can be integrated as much as possible to reduce the work required to validate on the server and the client. But be assured you must do both.
If bypassing the client validation (by means of DOM manipulation) is avoiding the server validation (which it seems you are indicating) then your server validation for this instance may not be employed appropriately. You should be invoking your server validation again in your controller action or in a service layer. The scenario you describe should not be defeating your server validation.
With the scenario you describe, the DataAnnotation attributes method should be sufficient. It seems that you simply need to make a few code changes to ensure that your server validation is invoked also when submitting the form.
I paired xVal with DataAnnotations and have written my own Action filter that checks any Entity type parameters for validation purposes. So if some field is missing in the postback, this validator will fill ModelState dictionary hence having model invalid.
Prerequisites:
my entity/model objects all implement IObjectValidator interface which declares Validate() method.
my attribute class is called ValidateBusinessObjectAttribute
xVal validation library
Action filter code:
public void OnActionExecuting(ActionExecutingContext filterContext)
{
IEnumerable<KeyValuePair<string, object>> parameters = filterContext.ActionParameters.Where<KeyValuePair<string, object>>(p => p.Value.GetType().Equals(this.ObjectType ?? p.Value.GetType()) && p.Value is IObjectValidator);
foreach (KeyValuePair<string, object> param in parameters)
{
object value;
if ((value = param.Value) != null)
{
IEnumerable<ErrorInfo> errors = ((IObjectValidator)value).Validate();
if (errors.Any())
{
new RulesException(errors).AddModelStateErrors(filterContext.Controller.ViewData.ModelState, param.Key);
}
}
}
}
My controller action is defined like this then:
[ValidateBusinessObject]
public ActionResult Register(User user, Company company, RegistrationData registrationData)
{
if (!this.ModelState.IsValid)
{
return View();
}
...
}
The DataAnnotation is certainly not enough. I use it extensively also to pre-validate my calls to the domain model to get better error reporting and fail as early as possible.
You can however tweak the DataAnnotation Model yourself to ensure properties with [Required] MUST be posted. (will follow up with code later today).
UPDATE
Get the source for DataAnnotations Model Binder and find this line in DataAnnotationsModelBinder.cs
// Only bind properties that are part of the request
if (bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey)) {
Change it to
// Only bind properties that are part of the request
bool contextHasKey = bindingContext.ValueProvider.DoesAnyKeyHavePrefix(fullPropertyKey);
bool isRequired = GetValidationAttributes(propertyDescriptor).OfType<RequiredAttribute>().Count() > 0;
if (contextHasKey || (!contextHasKey && isRequired)) {
I wrote my own ValidationService for MVC 1.0 by copying patterns from both xVal's DataAnnotationsRuleProvider and Microsoft's DataAnnotationsModelBinder (and Martijn's comments). The service interface is below:
public interface IValidationService
{
void Validate(object instance);
IEnumerable<ErrorInfo> GetErrors(object instance);
}
public abstract class BaseValidationService : IValidationService
{
public void Validate(object instance)
{
var errors = GetErrors(instance);
if (errors.Any())
throw new RulesException(errors);
}
public abstract IEnumerable<ErrorInfo> GetErrors(object instance);
}
The service is a validation runner that walks the property tree of the object instance it receives and actually executes the validation attributes that it finds on each property, building a list of ErrorInfo objects when attributes are not valid. (I'd post the whole source but it was written for a client and I don't know yet if I'm authorized to do so.)
You can then have your controllers, business logic services explicitly invoke validation when you are ready, rather than relying exclusively on the model binder for validation.
There are a couple of other pitfalls that you should be aware of:
The default DataTypeAttribute in data
annotations doesn't actually do any
data type validation, so you'll need
to write a new attribute that
actually uses xVal regular
expressions (or something else) to
perform server-side data type
validation.
xVal doesn't walk
properties to create client-side
validation, so you may want to make
some changes there to get more robust
client-side validation.
If I am allowed and have time, I will try to make more source available...
See codeProject Server-side Input Validation using Data Annotations
Input validation can be done automatically on the client side in
ASP.NET MVC or explicitly validating the model against the rules. This
tip will describe how it can be done manually on the server-side of an
ASP.NET applications or within the repository code of WPF
applications.
// Use the ValidationContext to validate the Product model against the product data annotations
// before saving it to the database
var validationContext = new ValidationContext(productViewModel, serviceProvider: null, items:null);
var validationResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(productViewModel, validationContext,validationResults, true);

Resources