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

心已入冬 提交于 2019-12-01 05:03:22

问题


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 submitted (for both views) if left blank or not within range. However, I have one view that should be able to allow empty or null values to be saved for a property whereas another view needs to require information to be entered or selected before it lets it through. In other words, I'd like to turn off the validator on the property within the MODEL for one view and leave it on for the other view. Here's the example code:

MODEL:

[Range(1, 999, ErrorMessage = "A submittal is required")]
public int SubmittalId { get; set; }

VIEW #1:

 <label>@Model.AuditDoc.SubmittalsLabel.ConfigurableLabelDesc</label> @Html.ValidationMessageFor(x => x.AuditDoc.SubmittalId) @Html.DropDownListFor(x => x.AuditDoc.SubmittalId, new SelectList(Model.AuditDoc.ListOfSubmittals, "Id", "Name"))

VIEW #2:

 <label>@Model.AuditDoc.SubmittalsLabel.ConfigurableLabelDesc</label> @Html.DropDownListFor(x => x.AuditDoc.SubmittalId, new SelectList(Model.AuditDoc.ListOfSubmittals, "Id", "Name"))

As you can see, I would like to disable that validator data annotation for View #2 and leave it on for View #1.


回答1:


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




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/11874026/is-it-possible-to-toggle-validation-data-annotations-on-off-in-mvc-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!