I have an mvc form with multiple submit buttons - 'Save Draft' and 'Publish'. The objective is to skip both client side(javascript/unobstructive) validation and server side validation when the 'Save Draft' button is clicked and the form is submitted. But I do need to trigger both validation if the 'Publish' button is clicked.
My research has led me to few solutions.
Client Side -By writing a jquery plugin
(function ($) {
$.fn.turnOffValidation = function (form) {
var settings = form.validate().settings;
for (var ruleIndex in settings.rules) {
delete settings.rules[ruleIndex];
}
};
})(jQuery);
and invoking it like
$('#btnSaveDraft').click(function () {
$(this).turnOffValidation(jQuery('#myForm'));
});
Server Side - But for the server side, the only solution I could find is to remove the errors from the ModelState. I have done it in an Action Attribute so that it is reusable and easy to use.
[AttributeUsage(AttributeTargets.All)]
public class IgnoreValidationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var modelState = filterContext.Controller.ViewData.ModelState;
//modelState.Clear();
foreach (var modelValue in modelState.Values)
{
modelValue.Errors.Clear();
}
}
}
But this does not completely serve my purpose. Why should we trigger the validation and clear the errors if we can prevent that from happening? Is this possible?
Are there any ways to prevent the server validation happening at the first place rather than clearing the validation resulted errors?
You can introduce a variable in you viewModel called
IsDraft
.Then derive your viewModel from
IValidatableObject
Then implement its method like this : (just an example of custom server side validation)
This way you will have your server side validation triggered only when its not Draft.
Now for client side validation use implement
IClientValidatable
This is the method :
I believe this is a better approach than enabling disabling the validation.
refer to these link if you need help implementing custom client side validations:
Hope that helps
One option available is to override ModelBinder, see here.
Specifically, overriding OnPropertyValidating and returning false prevents the validation function from running as you would like.
MVC is still doing a bit of work in that it is reading the metadata (validation attributes) and iterating through them.
Either way, ModelBinder is the extensibility point you need to look at as this is what calls the validation logic.
See this link ASP.MVC Extensibility Points
Overflow and Bilal, Thanks for answering my question.
@Bilal: I use the same model for Save and Submit and does not want any attributes on Model, rather need something at a controller/action level.
In a search to find a better answer I have come up with something like this. I read this from another article, but lost the link. As soon as I get it I will update the same.
Add a new action filter attribute
Override the DataAnnotationModelMetadata
Now tell the provider to use our custom data annotation metadata and empty the validation if IgnoreValidationAttribute is present in an action method
Usage
Please don't forget to call this in your Application_Start for the wireup 'ModelMetadataProviders.Current = new IgnoreValidationModelMetaDataProvider();
There are couple of concerns though.
Is there an early place we could manipulate the HttpContext than OnAuthorization() ?. I dont like the idea of overriding this to do something not related to authorization. Please note OnActionExecuting() will be too late in the MVC pipeline to do this(I tried this and is not working).
Is there a better way to do this than adding a key to HttpContext and using it later?