Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally validating portions of an ASP.NET MVC Model with DataAnnotations?

I have certain panels on my page that are hidden under certain circumstances.

For instance I might have a 'billing address' and 'shipping address' and I dont want to validate 'shipping address' if a 'ShippingSameAsBilling' checkbox is checked.

I am trying to use the new DataAnnotations capabilities of ASP.NET MVC 2 (preview 1) to achieve this.

I need to prevent validation of the 'shipping address' when it is not displayed and need to find the way way to achieve this. I am talking mainly server side as opposed to by using jquery.

How can I achieve this? I have had several ideas, related to custom model binding but my current best solution is below. Any feedback on this method?

like image 215
Simon_Weaver Avatar asked Aug 30 '09 03:08

Simon_Weaver


People also ask

How do you validate model data using DataAnnotations attributes?

ComponentModel. DataAnnotations namespace includes the following validator attributes: Range – Enables you to validate whether the value of a property falls between a specified range of values. RegularExpression – Enables you to validate whether the value of a property matches a specified regular expression pattern.

What is DataAnnotations MVC?

DataAnnotations is used to configure your model classes, which will highlight the most commonly needed configurations. DataAnnotations are also understood by a number of . NET applications, such as ASP.NET MVC, which allows these applications to leverage the same annotations for client-side validations.


2 Answers

For the CheckoutModel I am using this approach (most fields hidden):

[ModelBinder(typeof(CheckoutModelBinder))]
public class CheckoutModel : ShoppingCartModel
{        
    public Address BillingAddress { get; set; }
    public Address ShippingAddress { get; set; }
    public bool ShipToBillingAddress { get; set; }
}

public class Address
{
    [Required(ErrorMessage = "Email is required")]
    public string Email { get; set; }

    [Required(ErrorMessage = "First name is required")]
    public string FirstName { get; set; }

    [Required()]
    public string LastName { get; set; }

    [Required()]
    public string Address1 { get; set; }
}

The custom model binder removes all ModelState errors for fields beginning with 'ShippingAddress' if it finds any. Then 'TryUpdateModel()' will return true.

    public class CheckoutModelBinder : DefaultModelBinder
    {
        protected override void OnModelUpdated(ControllerContext controllerContext,
                                               ModelBindingContext bindingContext) {

            base.OnModelUpdated(controllerContext, bindingContext);

            var model = (CheckoutModel)bindingContext.Model;

            // if user specified Shipping and Billing are the same then 
            // remove all ModelState errors for ShippingAddress
            if (model.ShipToBillingAddress)
            {
                var keys = bindingContext.ModelState.Where(x => x.Key.StartsWith("ShippingAddress")).Select(x => x.Key).ToList();
                foreach (var key in keys)
                {
                    bindingContext.ModelState.Remove(key);
                }
            }
        }    
    }

Any better solutions?

like image 102
Simon_Weaver Avatar answered Oct 04 '22 19:10

Simon_Weaver


http://bradwilson.typepad.com/blog/2009/04/dataannotations-and-aspnet-mvc.html

like image 31
andrewbadera Avatar answered Oct 04 '22 17:10

andrewbadera