Edit: It is assumed that you are using MVC 3. Unfortunately, my code is in VB.NET, since I have to use it at work.
So that everything is fine with a new unobtrusive check, you need to do a few things. I passed through them a couple of weeks ago.
First, create your own attribute class that inherits from ValidationAttribute . A simple RequiredIf attribute class is below:
Imports System.ComponentModel Imports System.ComponentModel.DataAnnotations <AttributeUsage(AttributeTargets.Field Or AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)> _ Public NotInheritable Class RequiredIfAttribute Inherits ValidationAttribute Private Const _defaultErrorMessage As String = "'{0}' is required." Private ReadOnly _dependentProperty As String Private ReadOnly _targetValues As Object() Public Sub New(dependentProperty As String, targetValues As Object()) MyBase.New(_defaultErrorMessage) _dependentProperty = dependentProperty _targetValues = targetValues End Sub Public Sub New(dependentProperty As String, targetValues As Object(), errorMessage As String) MyBase.New(errorMessage) _dependentProperty = dependentProperty _targetValues = targetValues End Sub Public ReadOnly Property DependentProperty() As String Get Return _dependentProperty End Get End Property Public ReadOnly Property TargetValues() As Object() Get Return _targetValues End Get End Property Public Overrides Function FormatErrorMessage(name As String) As String Return String.Format(Globalization.CultureInfo.CurrentUICulture, ErrorMessageString, name) End Function Protected Overrides Function IsValid(value As Object, context As ValidationContext) As ValidationResult ' find the other property we need to compare with using reflection Dim propertyValue = context.ObjectType.GetProperty(DependentProperty).GetValue(context.ObjectInstance, Nothing).ToString() Dim match = TargetValues.SingleOrDefault(Function(t) t.ToString().ToLower() = propertyValue.ToLower()) If match IsNot Nothing AndAlso value Is Nothing Then Return New ValidationResult(FormatErrorMessage(context.DisplayName)) End If Return Nothing End Function End Class
Then you need to implement the validator class. This class is responsible for ensuring that MVC knows the client validation rules necessary for an unobtrusive validation library to work.
Public Class RequiredIfValidator Inherits DataAnnotationsModelValidator(Of RequiredIfAttribute) Public Sub New(metaData As ModelMetadata, context As ControllerContext, attribute As RequiredIfAttribute) MyBase.New(metaData, context, attribute) End Sub Public Overrides Function GetClientValidationRules() As IEnumerable(Of ModelClientValidationRule) Dim rule As New ModelClientValidationRule() With {.ErrorMessage = ErrorMessage, .ValidationType = "requiredif"} rule.ValidationParameters("dependentproperty") = Attribute.DependentProperty.Replace("."c, HtmlHelper.IdAttributeDotReplacement) Dim first As Boolean = True Dim arrayString As New StringBuilder() For Each param In Attribute.TargetValues If first Then first = False Else arrayString.Append(",") End If arrayString.Append(param.ToString()) Next rule.ValidationParameters("targetvalues") = arrayString.ToString() Return New ModelClientValidationRule() {rule} End Function End Class
Now you can register everything in the Global.asax application launch method:
DataAnnotationsModelValidatorProvider.RegisterAdapter(GetType(RequiredIfAttribute), GetType(RequiredIfValidator))
This gives you 90% of the way. Now you just need to tell the jQuery validate and MS unobtrusive level of validation how to read your new attributes:
/// <reference path="jquery-1.4.1-vsdoc.js" /> /// <reference path="jquery.validate-vsdoc.js" /> /* javascript for custom unobtrusive validation ==================================================== */ (function ($) { // this adds the custom "requiredif" validator to the jQuery validate plugin $.validator.addMethod('requiredif', function (value, element, params) { // the "value" variable must not be empty if the dependent value matches // one of the target values var dependentVal = $('#' + params['dependentProperty']).val().trim().toLowerCase(); var targetValues = params['targetValues'].split(','); // loop through all target values for (i = 0; i < targetValues.length; i++) { if (dependentVal == targetValues[i].toLowerCase()) { return $.trim(value).length > 0; } } return true; }, 'not used'); // this tells the MS unobtrusive validation layer how to read the // HTML 5 attributes that are output for the custom "requiredif" validator $.validator.unobtrusive.adapters.add('requiredif', ['dependentProperty', 'targetValues'], function (options) { options.rules['requiredif'] = options.params; if (options.message) { options.messages['requiredif'] = options.message; } }); } (jQuery));
Hope this helps, it was a real pain to work.