Question

I have the following custom required attribute code:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public sealed class AddressRequiredAttribute : RequiredAttribute, IClientValidatable
{
    /// <summary>
    /// The _property name
    /// </summary>
    private string _propertyName;

    /// <summary>
    /// Initializes a new instance of the <see cref="AddressRequiredAttribute"/> class.
    /// </summary>
    /// <param name="propertyName">Name of the property.</param>
    public AddressRequiredAttribute(string propertyName)
        : base()
    {
        _propertyName = propertyName;
    }

    /// <summary>
    /// Checks that the value of the required data field is not empty.
    /// </summary>
    /// <param name="value">The data field value to validate.</param>
    /// <returns>
    /// true if validation is successful; otherwise, false.
    /// </returns>
    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        if (context.ObjectType.BaseType == typeof(AddressModel))
        {
            PropertyInfo property = context.ObjectType.GetProperty(_propertyName);
            if (property != null && (bool)property.GetValue(context.ObjectInstance))
            {
                return base.IsValid(value, context);
            }
        }

        return ValidationResult.Success;
    }

    /// <summary>
    /// When implemented in a class, returns client validation rules for that class.
    /// </summary>
    /// <param name="metadata">The model metadata.</param>
    /// <param name="context">The controller context.</param>
    /// <returns>
    /// The client validation rules for this validator.
    /// </returns>
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        string errorMessage = this.ErrorMessage;

        // Get the specific error message if set, otherwise the default
        if (string.IsNullOrEmpty(errorMessage) && metadata != null)
        {
            errorMessage = FormatErrorMessage(metadata.GetDisplayName());
        }

        var clientValidationRule = new ModelClientValidationRule()
        {
            ErrorMessage = errorMessage,
            ValidationType = "requiredaddress"
        };

        return new[] { clientValidationRule };
    }

and the following jquery for the client side validation which is run on window.load:

$.validator.addMethod('requiredaddress', function (value, element, params) {
    return value != '';
}, '');

$.validator.unobtrusive.adapters.add('requiredaddress', {}, function (options) {
    options.rules['requiredaddress'] = true;
    options.messages['requiredaddress'] = options.message;
});

However, the clientside doesn't kick in so I get the normal clientside validation working, then the form will submit but come back with the custom errors after postback. All the examples that I have looked at say that my code should be correct so I'm not sure what is wrong here.

Can anyone see anything obvious I'm doing wrong here, thanks

Was it helpful?

Solution

I did something similar to this and found that if I put the code in the document.ready on window.load it wouldn't work. In the end I went with using the following code placed after the jquery validate scripts:

(function ($) {
    $.validator.addMethod('requiredaddress', function (value, element, params) {
        return value != '';
    }, 'Clientside Should Not Postback');

    // i think you should be able to use this as your adapter
    $.validator.unobtrusive.adapters.addBool('requiredaddress');
})(jQuery);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top