I have two separate VIEWS accessing the same MODEL. When I put the validator data annotations on the model, it works as advertised and prevents the data from being submitte
I solved this problem using a different approach.
The trick is not to disable validation per-se, but to clear any inappropriate validation errors before the controller's action is invoked (so ModelState.IsValid returns true).
If a Model (or ViewModel) object requires custom validation then it implements an interface I defined called ICustomValidation
which looks like this:
public interface ICustomValidation {
void PerformValidation(ModelStateDictionary modelState);
}
My BaseController
class (which all of my controllers subclass) has this method override:
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
base.OnActionExecuting(filterContext);
// Unfortunately it seems this is the only way to get the Model object
if( filterContext.ActionParameters.ContainsKey("model") ) {
Object model = filterContext.ActionParameters["model"];
ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState; // ViewData.Model always returns null at this point.
ICustomValidation modelValidation = model as ICustomValidation;
if( modelValidation != null ) {
modelValidation.PerformValidation( modelState );
}
}
}
So in an example ViewModel class, if I want to disable (or rather: disregard) certain validation errors then it just needs to do this:
public class SomeModel : ICustomValidation {
[Required]
public Boolean NamePresent { get; set; }
[Required]
public String Name { get; set; }
public void PerformValidation(ModelStateDictionary modelState) {
if( !NamePresent ) dict.Remove("Name");
}
}
In my actual code there's a bit more logic that clears the ModelStateDictionary in a model-recursive and by-prefix method which keeps it robust.
My solution does not match your problem exactly, but using a similar approach you should be able to get it to work for you.
This isn't possible via the default set of data annotations.. however, you have the choice of using 2 separate view models or writing your own validationAttribute.
I wrote this once.. although I loathed using it..
public class RequiredOnAttribute : ValidationAttribute
{
public string[] URLs { get; set; }
public override bool IsValid(object value)
{
if (URLs.Contains(System.Web.HttpContext.Current.Request.Url.AbsolutePath))
{
if (string.IsNullOrEmpty(value as string))
{
return false;
}
}
return true;
}
}
Usage:
[RequiredOn(URLs = new string[] { "/create", "/edit" })]
public string MyModelField { get; set; }
You could do the same for Range, RegEx, etc..
I too would suggest using a different view model object. This article has a nice example of how to implement it cleanly http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/
Alternatively, you could simply not call ModelState.IsValid on the controller.