Search code examples
vb.netasp.net-mvc-5data-annotationsunobtrusive-validation

How can I add custom client side validation to validation that was generated from annotations in MVC5 VB.NET


I have added a number of annotations to do simple required field validation in a modal form. Now I need to do a somewhat convoluted check for uniqueness on a couple of the fields involved.

I want to avoid using a custom annotation to do this as the fields that require validation within the model require extra information that does not exist in the model.

I want to be able to add a new rule to the existing validation via script.

Unfortunately I can't seem to get both the new rule and the existing ones to work at the same time.

If I do the following, then only the new rule gets applied, all the existing rules (required fields etc.) disappear.

    jQuery.validator.addMethod("uniqueresourceid", 
        function(value, element, options) {
            return ResourceIDValidation(options.resourceSet, value, options.originalresourceidpropertyname);
        }, "This resource ID is already inuse.");   

    var validator = $('#InstitutionModalForm').validate();

    $('#Institution_NameResourceID').rules("add", {
        uniqueresourceid: {
            resourceSet: "Institutions",
            resourceId: $('#NameResourceID').val(),
            oldResourceId: "OriginalNameResourceID"
        }
    });

    function ResourceIDValidation(ResourceSet, ResourceID, OldResourceIDField) {
        var valid = false;
        $.ajax({
            type: "POST",
            url: "@Url.Action("ValidateResourceID", "Admin")",
            traditional: true,
            contentType: 'application/json; charset=utf-8',
            async: false,
            data: JSON.stringify({
                ResourceSet: ResourceSet,
                ResourceID: ResourceID,
                OldResourceID: $('#' + OldResourceIDField).val(),
            }),
            success: function (result) {
                 valid = result;
            },
            error: function (result) {
                console.log(data);
                valid = false;
            }
        });
        return valid;
    }

If I remove the 'var validator =...' line, then only the original validation (required fields etc.) fires.

I can't see any reason why this shouldn't be possible, but I can't seem to figure out how to make it work.

I'm not really clear on how the unobtrusive stuff does it's magic, but shouldn't there be a way to hook into whatever validator is being generated by the server side annotations so that I can add a new rule in the JS?


Solution

  • Strictly speaking, this is possible but I can see some very important reasons why you wouldn't want to do this.

    Most importantly, this creates a client side validation only. This means if someone nefariously submits the form, or if they don't have JS enabled, that your server side code will not do this validation and probably break.

    In addition to that, it makes your code harder to maintain as the validation is not handily visible in your code as it would be with an annotation.

    While it is probably a very bad idea to do this, this is how you could make it happen. Adding this code above the "addMethod" caused it to validate as I initially intended.

    $('#NameResourceID').attr("data-val", "true");
    $('#NameResourceID').attr("data-val-uniqueresourceid", "Resource ID must be unique.");
    $('#NameResourceID').attr("data-val-uniqueresourceid-resourceset","institutions");
    $('#NameResourceID').attr("data-val-uniqueresourceid-originalresourceidpropertyname","OriginalNameResourceID");
    

    Do this instead: Implement a custom validation annotation as Stephen Muecke suggested in the question comments. It was more work, but in the end is far better practice. This was the most helpful (to me) tutorial I could find on the subject.