Is it possible to toggle Validation Data Annotations on/off in MVC 3?

前端 未结 3 533
别跟我提以往
别跟我提以往 2021-01-13 20:36

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

相关标签:
3条回答
  • 2021-01-13 20:48

    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.

    0 讨论(0)
  • 2021-01-13 21:05

    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..

    0 讨论(0)
  • 2021-01-13 21:06

    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.

    0 讨论(0)
提交回复
热议问题