1

I am currently building a booking form using MVC within Umbraco. The properties I care about are as follows:

    public class BookingModel{

        public bool Previous { get; set; }
        public bool Next { get; set; }
        public int Stage { get; set; }
        public int Price { get; set; }

        public Tour_Instance Tour_Instance { get; set; }
        public Passenger_Count Passenger_Count {get; set;}
        public Passenger_Details Passenger_Details { get; set; }
        public BookingConfirmation Booking_Confirmation { get; set; }
    }

    public class Passenger_Details{
       [UmbracoDisplayName("Booking.Display.PhoneMobile")]
       public string Phone_Mobile { get; set; }

       [UmbracoDisplayName("Booking.Display.PhoneHome")]
       public string Phone_Home { get; set; }

       [UmbracoDisplayName("Booking.Display.PhoneWork")]
       public string Phone_Work { get; set; }
    }

The UmbracoDisplayName annotation simply retrieves a value from a dictionary in Umbraco that changes the value of the label displayed next to each item. Ideally, I would like to create a custom data annotation that ensures at least one of the properties shown above (Phone_mobile, Phone_Home, Phone_Work) has a value.

Currently I am doing the following in the controller:

if (string.IsNullOrWhiteSpace(model.Passenger_Details.Phone_Mobile) && string.IsNullOrWhiteSpace(model.Passenger_Details.Phone_Home) && string.IsNullOrWhiteSpace(model.Passenger_Details.Phone_Work))
                    {
                        ModelState.AddModelError("Passenger_Details.Phone_Mobile", Umbraco.GetDictionaryValue("Booking.Validation.OnePhoneRequired"));
                        ModelState.AddModelError("Passenger_Details.Phone_Home", string.Empty);
                        ModelState.AddModelError("Passenger_Details.Phone_Work", string.Empty);
                    }

This does the job but doesn't really fit with convention. My question is, how would I create the data annotation so that it runs a comparison of all properties of the model that have the annotation and checks whether the value is null or empty?

I know how to create a custom annotation its basically just the logic I would have to follow that I am struggling to come up with.

Any assistance would be greatly appreciated.

jezzipin
  • 4,110
  • 14
  • 50
  • 94

1 Answers1

2

To accomplish this task you can create a class inherited from ValidationAttribute and implement something similar to:

public class OnePhoneRequiredAttribute : ValidationAttribute
{
  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    var passengerDetails = value as Passenger_Details;
    if (passengerDetails == null)
    {
        // handle depending on your situation
    }

    if (string.IsNullOrWhiteSpace(passengerDetails.Phone_Mobile) 
        && string.IsNullOrWhiteSpace(passengerDetails.Phone_Home) 
        && string.IsNullOrWhiteSpace(passengerDetails.Phone_Work))
    {   
        return new ValidationResult(Umbraco.GetDictionaryValue("Booking.Validation.OnePhoneRequired"));
    }

    return null;
  }
}

Then add this attribute to your model:

[OnePhoneRequired]
public Tour_Instance Tour_Instance { get; set; }

EDIT: Also take a look on FluentValidation library, it can simplify a lot your validation logic.

Andrei Mihalciuc
  • 2,148
  • 16
  • 14