Disable Model Validation in Asp.Net MVC - asp.net-mvc

How do I disable Model validation for a single Action in a Controller ?
Or can I do it per model by registering the model type at startup somewhere ?
I want the ModelBinder to bind to the model, but afterwards it should not perform the model validation.
The reason why i dont want validation to happen is because i am trying to move the logic from the controllers to a service layer which will be responsible for validating the models as i cant assume that models being passed to a service contains valid data.
As I understand this is the recommend approach (to not have logic in the controllers), so I find it a bit strange that i cant seem to find anything about how the model validation can be disabled (per action or per model type).
Please notice that I dont want to disable model validation for the entire webapplication (by removing the validation providers), and i dont want to disable the input validation that checks for malicious code being posted.
UPDATE
I am using .Net 4.0 and MVC 3 Preview 1

Just remove the items you don´t need before checking if the model is valid
ModelState.Remove("Email");
if (ModelState.IsValid)
{
// your logic
}

I've solved this problem with this code:
public ActionResult Totals(MyModel model)
{
ModelState.Clear();
return View(model);
}
Not sure it's the right way though.

Unfortunately there seems to be no easy way to disable the model validation happening in the ModelBinder except for registering every single model type you don’t want to validate (including nested complex types) with a specific ModelBinder. It can be done with the following code:
ModelBinders.Binders[typeof(MyModelType)] = new NonValidatingModelBinder();
Creating a SkipValidationAttribute that can be attached to action methods or action method parameters doesn’t seem possible as it should be implemented in the ControllerActionInvoker, but there is no way of letting the ModelBinder know that it should do any validation in the SetProperty() and OnModelUpdated methods when calling BindModel() in the GetParameterValue() method.

I definitely dislike this addition in the 2.0 version, because, as you stated in your question, validation makes more sense in the Service layer. In this way you can reuse it in other non-web applications, and test it more easily without having to mock the auto-validation mechanism.
Validation in Controller layer is pointless because in this part you can only verify model data and not business rules. For example, think of a service responsible of adding new comments and a user that wants to post a new one, the data in the comment he/she is posting may be valid, but what happens if the user is banned to comment because of misbehavior in the past? You should do some validation in the Service layer to ensure this is not happening, and if it does, throwing an exception. In short, validation must be done in the Service layer.
I use xVal as my Validation framework because it's compatible with the DataAnnotationModel, allows me to place validation wherever I want and performs client-side validation without extra-effort, even remote-client side. This is how I use it at the beginning of each of my services, for example, a login service:
public void SignIn(Login login) {
var loginErrors = DataAnnotationsValidationRunner.GetErrors(login);
// Model validation: Empty fields?
if (loginErrors.Any())
throw new RulesException(loginErrors);
// Business validation: Does the user exist? Is the password correct?
var user = this._userRepository.GetUserByEmail(login.Email);
if (user == null || user.Password != login.Password)
throw new RulesException(null, "Username or password invalids");
// Other login stuff...
}
Simple, web-independent and easy... then, in the Controller:
public RedirectResult Login(Login login) {
// Login the user
try {
this._authenticationRepository.SignIn(login);
} catch (RulesException e) {
e.AddModelStateErrors(base.ModelState, "Login");
}
// Redirect
if (base.ModelState.IsValid)
return base.Redirect(base.Url.Action("Home"));
else return base.Redirect(base.Url.Action("Login"));
}

I would recommend you perform validation in both places rather than trying to turn off validation in the UI. I understand your point that the service cannot assume that it's being passed valid data - that is a valid concern and is the reason your service should have validation. But you should also have validation in your UI. This is also nice because you can have client-side validation to prevent user errors and give you users a better experience.

I know that this already been answered but what you really needed was to extend the DataAnnotationsValidatorProvider and override the GetValidators method.
Then, on startup, you would remove the DataAnnotationsValidatorProvider from ModelValidatorProviders.Providers and add your new one.
Needless to say, if you simply don't want any validation at all, you can simply have the GetValidators method returning an empty collection.
In my case, I need to remove validation only when submitting the forms while still keeping the client-side validation, hence the following:
public class DynamicModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
if (context.HttpContext.Request.HttpMethod == "POST")
{
return new ModelValidator[] { };
}
return base.GetValidators(metadata, context, attributes);
}
}

I use
[ ValidateInput( false )]
Not sure if this prevents model validation, or only IIS submit validation.

Related

Recommended approach for model validation that needs to touch the Db

Up to now, most of our validation is performed using validation attributes on our view models.
One additional validation check we need to perform is to validate that a string doesn't already exist in our database.
Originally I was just handling this check within the controller action and then adding an error into ModelState if required. However, I would rather make use of the built-in validation infrastructure.
One method I tried was implementing IValidateableObject on my viewmodel. This feels a bit wrong as I'm calling DependencyResolver:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var viewModel = validationContext.ObjectInstance as EditPostViewModel;
if (viewModel != null)
{
var slug = (Slug)viewModel.Slug;
var repo = DependencyResolver.Current.GetService<IRepository<Post>>();
var existing = repo.Get(p => p.Slug == slug && p.Id != viewModel.Id);
if (existing != null)
yield return new ValidationResult("Duplicate slug.", new[] { "Slug" });
}
}
Another approach I thought about was using a custom ValidationAttribute. To me this only makes sense if I can re-use it on multiple viewmodels and to re-use it I need to be able to construct a generic repository interface (as per the above code) as I may need IRepository<Foo> or IRepository<Bar> depending on the Model.
Remote Validation is great but I still need to the validation server side.
So what would people recommend or have used themselves to achieve something similar.
Note that I do have unique database constraints on this column but don't want to fall back to exception handling to perform this validation.
Solution
I had a look as the asp.net article #Darin suggested. This approach definitely works, but the article is a bit flawed in that whilst it manages to decouple the validation service away from any direct references to ModelState, you instead end up with a circular dependency where controller depends on the validation service and the validation service depends on ModelState (via a wrapper); which doesn't exist until the controller is created. Nice!
Instead I exposed the IValidationDictionary as a public property on my validation service and set this in my controllers constructor:
slugValidator.ValidationDictionary = new ModelStateWrapper(this.ModelState);
The rest is kind of application specific but essentially I created a validator for each type of "slugable" entity I wanted to validate. These were then injected by my container.
public interface ISlugValidator<TEntity> where TEntity : ISlugable {
IValidationDictionary ValidationDictionary { get; set; }
bool ValidateSlug(Guid? entityId, Guid featureId, Slug slug);
}
I call ValidateSlug(...) just before I check ModelState.IsValid in my controller actions.
This is a good solution for the level of validation I need currently and the fact that most of it can be handled using Data annotations. If my validation/business rules get more complex I will probably switch to FluentValidation (this also works well with Depenency Injection) as it's better suited for externalizing validation logic.
I would recommend doing this type of validation at the service layer and not bother with data annotations.

MVC3 Service Layer Validation. Returning Exception, Custom Object, Model State Dictionary?

Just curious on your thoughts or experiences around service layer validation.
I have to process fairly standard validation such as "object with name property doesn't already exist", but I wasn't sure how to return these validation failures back to the controller.
My initial thought was to implement a standard List<ValidationError> but I've seen it done each and every way so was curious the pros/cons of each.
Thanks for any input.
If you go with System.ComponentModel.DataAnnotations entries you can (as you seem to know) decorate your properties with required and many more tags
public class Person
{
[Required(ErrorMessage="object with name property doesn't already exist")]
public string Name { get; set; }
}
although I personally use ViewModels rather than exposing domain mdoels to the view, your controller action can now do something like:
[HttpPost]
public ActionResult SavePerson(Person model)
{
if (ModelState.IsValid)
{
// your model validates - do things
return RedirectToAction("success view here");
}
return View(model);
}
This is one of the standard 'post' handler patterns in MVC. This is the simplest path to getting your object model validating in my opinion.
From there, there are a few other options - your domain object can implement IValidatedableObject and you can yield return the errors (see http://buildstarted.com/2010/09/20/mvc-3s-ivalidatableobject/ as an example).
I'd recommend not mixing the two though, as if you are using dataannotations and have even a single invalid property, the IsValid method on IValidatableObject will not be called.
From there, there's lots you can do with custom validation attributes (the extended version of IsValid seems to give you more flexibility http://msdn.microsoft.com/en-us/library/gg480674%28v=vs.98%29.aspx)
Hope some of the above helps - once you get past the basics there's a lot you can do with it and things like client validation of custom attributes etc. are all fun.
Cheers,
Terry
[edit to add:
After re-reading your post, it may be that you want to only validate at the service layer? If so, I've used the following approach:
public void Setname(string newName)
{
Validator.ValidateProperty(newName, new ValidationContext(this, null, null) { MemberName = "Name" });
Name = newName;
}
obviously your Name property would need a { get; private set; } for this, though you could always add the Validator.ValidateProperty into an extended setter for the public property either.
]
On a new project I'm working on (first time mvc) I've been using the ms code contracts (which throw exceptions) and do all the validation on my domain objects themselves. For things that can't be validated there (such as validations that require database access) I validate in my services and throw exceptions. Additionally like the poster above I have whole separate view models for everything that have data annotations validators on them. The exceptions bubble up and I catch them in the controller and append to the ModelState. There's a lot of overlap with those and the view model validation but it's not much extra effort and allows me to vary the validation per view and yet still have the "core" validations be required.
The book pro asp mvc 2 has another nice way - write a class that inherits Exception and contains a collection of errors. Then you do your validations, add to the collection then throw the exception then he catches it in the controller and copies over to ModelState. This method will let you catch ALL the errors in one exception instead of just one at the service layer.

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);

Partial Validation ASP.NET MVC

I've read a number of articles now in regard to validation and asp.net mvc and the majority tend to point to validation in the model. The problem I see with all of them is that they don't handle different scenarios, or at least, they don't show how they would be achieved e.g.
When creating or updating a user account the email address must match the email confirmation input. This email confirmation input isn't part of the model it's purely to assist correct user input, this might be called a virtual property. When a user logs in using their email address the validation shouldn't try and match the email against a confirmation input, however, in all the examples I've seen there is no way to differentiate between scenarios where the same data is validated in a different way.
Can anybody point me to any mvc validation articles that handle the above types of problem? Or does anybody have any advice on best practices to handle validation like this?
I had thought about introducing a "validation action" such as create, read, update, delete, and then I could validate the same bit of data depending on the context in which it is being used. Anybody have any thoughts on doing things in this manner?
Thanks in advance for any help
This is why I'm using Validators separated from Models. So, I have IValidator and different validators. For instantiate validator I use DI Container (StructureMap for example).
It was described (not by me) here:
Issues with my MVC repository pattern and StructureMap
According to my experience
1. Validator should be decoupled from controller into separate Service layer like, for instance, showed in this tutorial:
http://www.asp.net/learn/mvc/tutorial-38-cs.aspx
2. Service methods may encapsulate all the kind of validation. For example:
public bool PlaceBooking(Booking booking)
{
//Model validation
IEnumerable<ErrorInfo> errors = DataAnnotationsValidationRunner.GetErrors(booking);
if (errors.Any())
_validationDictionary.AddErrors("error", errors);
// Business rule: Can't place bookings on Sundays
if(booking.ArrivalDate.DayOfWeek == DayOfWeek.Sunday)
_validationDictionary.AddError("ArrivalDate", "Bookings are not permitted on Sundays");
if (!_validationDictionary.IsValid) return false;
//Errors comming from Data Access Layer
try
{
return _dao.Save(booking);
}
catch (DBExecutionException ex)
{
if (ex.ResultCode == ResultCodes.RES_UNIQUEINDEX)
_validationDictionary.AddError("error", "Booking already exists.");
else
_validationDictionary.AddError("error", "Some other DB issue happens.");
}
return false;
}

Using MVC and fluent Nhibernate, how do I validate unique fields on my ViewModel before I bind them to my Domain Object and Save them?

I have a website where I allow users to create new Part records. I'm trying to figure out the best way to validate specific fields for uniqueness. I want to make sure that somebody doesn't try to add a Part with PartNumber 1234 if that PartNumber already exists on a different Part.
The Web Application is using Asp.net MVC with fluent nHibernate for mapping my objects to the database. I'm using Castle validation on my view models for things like ValidateNonEmpty, ValidateRange, etc. Should I use the ValidateSelf method to query the repository to see if that part number already exists? Something doesn't feel right about using my Repository on the ViewModel.
Would it be better for me to place that logic on the controller action? That doesn't seem right because I expect my ViewModel to already be Validated at the point (during ModelBind).
Or maybe its none of the above. Thanks for any help on this one.
UPDATE
Ok, not sure if this will help, but here is what my Save action looks like for a typical Create Action in my project:
public ActionResult Create(PartViewModel viewModel)
{
//I think I'd like to know if its Valid by this point, not on _repository.Save
if(ModelState.IsValid)
{
try
{
var part = _partCreateViewModelMap.MapToEntity(viewModel);
_repository.Save(part);
return Redirect("~/Part/Details/" + part.Id);
}
catch (Exception e)
{
// skip on down...
}
}
// return view to edit
return View(viewModel);
}
I have been asked this question many times. My friends were worried about whether they can perform data access from the validator code. The answer is simple. If you need to do this, you should do it. Usually we need to do such checks at each level of abstraction. And after all checks you should be ready to catch an exception, caused by unique constraint violation.
If you define a unique constraint within the database, then why not delegate the responsibility to check for whether a unique value already exists to the database? Using NHibernate, you can use the NHibernate.Exceptions.ISQLExceptionConverter interface to capture and transform known errors relating to constraint violations. You can also use NHibernate.Exceptions.IViolatedConstraintNameExtracter implementers (see NHibernate.Exceptions.TemplatedViolatedConstraintNameExtracter) to get at the grubby details of your database exception, and transform it into a user-friendly message, repackage as a validation exception of your chosing and catch it in the relevant controller.
Example of a quick, very specific quick and dirty exception converter from one of my projects:
Imports NHibernate
Imports NHibernate.Exceptions
Imports System.Data.SqlClient
Imports System.Data.Common
Namespace NHibernate
Public Class ConstraintViolationExceptionConverter
Implements ISQLExceptionConverter
Public Function Convert(ByVal adoExceptionContextInfo As Global.NHibernate.Exceptions.AdoExceptionContextInfo) As System.Exception Implements Global.NHibernate.Exceptions.ISQLExceptionConverter.Convert
Dim dbEx As DbException = ADOExceptionHelper.ExtractDbException(adoExceptionContextInfo.SqlException)
If TypeOf dbEx Is SqlException Then
Dim sqlError As SqlException = DirectCast(dbEx, SqlException)
Select Case sqlError.Number
Case 547
Return New ConstraintViolationException(adoExceptionContextInfo.Message, adoExceptionContextInfo.SqlException)
End Select
End If
Return SQLStateConverter.HandledNonSpecificException(adoExceptionContextInfo.SqlException, adoExceptionContextInfo.Message, adoExceptionContextInfo.Sql)
End Function
End Class
End Namespace
Configured through the web.config/nhibernate-configuration/session-factory property element:
<property name="sql_exception_converter">csl.NHibernate.ConstraintViolationExceptionConverter, csl</property>
Edit: Should probably mention that the converter interface has changed in recent versions of NHibernate, the interface from this example is from NHibernate.dll v2.1.0.4000
I typically put a Service layer between my controllers and repositories.
The service layer would then handle the validation and calls to the repository.
Then, if there's a validation error in the service layer, I throw a custom exception, catch it in the controller, and inject the errors in to the model state.
I have no answer for your question but you can check sharparchitecture.net site. It contains some best practives for asp.net mvc and nhibernate. Also I can recommend you to check xval project and tutorials about Validating with Data Annotation Validators
I have found the solution that works for me is to
1.) Ask if the entity is valid to execute your validation work.
2.) After this is complete you should have something on your object to show it's valid or not (in my case I use a CSLA like concept of "broken rules").
3.) If you have something like this you can verify the object is valid before NHibernate tries to persist it as shown below.
The only issue with this approach is that you do need to implement an interface on each entity requiring validation. If you can live with this it will stop NHibernate from persisting the changes of an object that's not valid according to your rules.
using System;
using NHibernate;
using NHibernate.Event;
using Validation.Entities.Interfaces;
using Persistence.SessionBuilder;
namespace Persistence.Validation
{
public class ValidationEventListener : IPreInsertEventListener, IPreUpdateEventListener
{
public bool OnPreInsert(NHibernate.Event.PreInsertEvent #event)
{
var entityToInsert = #event.Entity as IBusinessBase;
if (entityToInsert != null)
{
if (entityToInsert.BrokenRules != null)
{
RollbackTransactionBecauseTheEntityHasBrokenRules();
}
}
return false;
}
public bool OnPreUpdate(NHibernate.Event.PreUpdateEvent #event)
{
var entityToUpdate = #event.Entity as IBusinessBase;
if (entityToUpdate != null)
{
if (entityToUpdate.BrokenRules != null)
{
RollbackTransactionBecauseTheEntityHasBrokenRules();
}
}
return false;
}
private void RollbackTransactionBecauseTheEntityHasBrokenRules()
{
try
{
ISession session = SessionBuilderFactory.GetBuilder().CurrentSession;
if (session != null)
{
session.Transaction.Rollback();
}
}
catch (Exception ex)
{
//this will force a rollback if we don't have a session bound to the current context
throw new NotImplementedException();
}
}
}
}
I would say this matters on your architecture. With MVC apps that I have done in the past we abstract away the domain stuff away from the web stuff and naturally we use dependency injection to avoid hard dependencies.
When it comes to validating the model when you are in the act of binding it, yes you could easily use the service, repository, or whatever you have next in your architecture in a ValidateSelf method. I think the question rises of what about that dependency.
If I remember correctly you can create your own custom binder that will use your dependency injection framework to plug-in any services your model needs for validation when you create it, call MVC's default binder to fill in the object, then call into Castle Validation's framework to do the validation. This isn't a fully thought solution, but hopefully it provokes some ideas.

Resources