Sql – OnFieldChanging Validation with Linq-to-SQL and MVC

asp.net-mvclinq-to-sql

I have the following partial methods in my partial class that is attached to an object in my Liq to SQL model.

The first validation check in each method works fine for checking a valid entry in each. However the second if statement is used to check that the user has set at least one of the fields, but the methods are never actually called when use leaves these fields empty. I have some of my validation in DataAnnotation tags, but I can't use the required attribute because its an "Either or" scenario.

Is there a way to stick with my current validation pattern and get this sort of validation into the model? (Backup plan is to code it in the controller)

partial void OnTelChanging(string value)
        {
            if (!PhoneValidator.IsValidNumber(value))
                _errors.Add("Tel", "Telephone No must be a valid UK phone number.");


            if (String.IsNullOrEmpty(this.Mob) && String.IsNullOrEmpty(this.Tel))
            {
                _errors.Add("Tel", "You must enter at least one contact number.");
                _errors.Add("Mob", "");
            }
        }

        partial void OnMobChanging(string value)
        {
            if (!PhoneValidator.IsValidNumber(value))
                _errors.Add("Mob", "Mobile must be a valid UK phone number.");


            if (String.IsNullOrEmpty(this.Mob) && String.IsNullOrEmpty(this.Tel))
            {
                _errors.Add("Tel", "You must enter at least one contact number.");
                _errors.Add("Mob", "");
            }
        }





 [Bind(Include = "EthnicOriginID,CreatedByUserID,AddressID,CarefirstNumber,Title,Forename,Surname,Dob,Tel,Mob,GuardianName,Notes,Archived")]
    [MetadataType(typeof(CustomerMetaData))]
    public partial class Customer : IDataErrorInfo
    {
        private Dictionary<string, string> _errors = new Dictionary<string, string>();

        partial void OnTelChanging(string value)
        {
            if (!String.IsNullOrEmpty(value) && !PhoneValidator.IsValidNumber(value))
                _errors.Add("Tel", "Telephone No must be a valid UK phone number.");


            if (String.IsNullOrEmpty(this.Mob) && String.IsNullOrEmpty(this.Tel))
            {
                _errors.Add("Tel", "You must enter at least one contact number.");
                _errors.Add("Mob", "");
            }
        }

        partial void OnMobChanging(string value)
        {
            if (!String.IsNullOrEmpty(value) && !PhoneValidator.IsValidNumber(value))
                _errors.Add("Mob", "Mobile must be a valid UK phone number.");


            if (String.IsNullOrEmpty(this.Mob) && String.IsNullOrEmpty(this.Tel))
            {
                _errors.Add("Tel", "You must enter at least one contact number.");
                _errors.Add("Mob", "");
            }
        }

        #region ToString Override

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return this.Surname + ", " + this.Forename;
        }

        #endregion ToString Override

        #region IDataErrorInfo Members

        public string Error
        {
            get
            {
                return string.Empty;
            }
        }

        public string this[string columnName]
        {
            get
            {
                if (_errors.ContainsKey(columnName))
                    return _errors[columnName];
                return string.Empty;
            }
        }

        #endregion
    }

    public class CustomerMetaData
    {
        #region EthnicOriginID

        [DisplayName("Ethnic Origin")]
        public int EthnicOriginID { get; set; }

        #endregion EthnicOriginID

        #region CreatedByUserID

        [DisplayName("Created By User")]
        [Required]
        public int CreatedByUserID { get; set; }

        #endregion CreatedByUserID

        #region AddressID

        [DisplayName("Address")]
        public int AddressID { get; set; }

        #endregion AddressID

        #region CarefirstNumber

        [DataType(DataType.Text)]
        [DisplayName("Carefirst Number")]
        [StringLength(8)]
        public string CarefirstNumber { get; set; }

        #endregion CarefirstNumber

        #region Title

        [DataType(DataType.Text)]
        [DisplayName("Title")]
        [StringLength(10)]
        public string Title { get; set; }

        #endregion Title

        #region Forename

        [DataType(DataType.Text)]
        [DisplayName("Forename")]
        [StringLength(25)]
        [Required]
        public string Forename { get; set; }

        #endregion Forename

        #region Surname

        [DataType(DataType.Text)]
        [DisplayName("Surname")]
        [StringLength(25)]
        [Required]
        public string Surname { get; set; }

        #endregion Surname

        #region Dob

        [DataType(DataType.DateTime)]
        [DisplayName("Dob")]
        public DateTime Dob { get; set; }

        #endregion Dob

        #region Tel

        [DataType(DataType.Text)]
        [DisplayName("Telephone No.")]
        [StringLength(11)]
        public string Tel { get; set; }

        #endregion Tel

        #region Mob

        [DataType(DataType.Text)]
        [DisplayName("Mobile")]
        [StringLength(11)]
        public string Mob { get; set; }

        #endregion Mob

        #region GuardianName

        [DataType(DataType.Text)]
        [DisplayName("Guardian Name")]
        [StringLength(50)]
        public string GuardianName { get; set; }

        #endregion GuardianName

        #region Notes

        [DataType(DataType.Text)]
        [DisplayName("Notes")]
        [StringLength(300)]
        public string Notes { get; set; }

        #endregion Notes
    }

Best Answer

Implement IDataErrorInfo. This will do what you want, and MVC picks it up automatically.