FluentValidation NotEqual client-side validation

I wanted client-side validation for NotEqual. I started out writing my own and got 90% of the way there, then I got a little stuck. A quick Google revealed an existing Gist – however, the original implementation was only for NotEqual property comparison and I need a value compariosn. So, I forked it and made it work for my needs.

(function ($) {
    $.validator.addMethod("notequal", function (value, element, param) {
        if (param.indexOf("#") == -1) return value != param;
        return value != $(param).val();
    }, $.validator.messages.notequal);

    $.validator.unobtrusive.adapters.add("notequal", ["field"], 
    function (options) {
        options.rules["notequal"] = options.params.field;
        if (options.message) options.messages["notequal"] = options.message;
    });
})(jQuery);
FluentValidationModelValidatorProvider.Configure(provider =>
{
    provider.Add(typeof(NotEqualValidator), 
        (metadata, context, description, validator) => 
        new NotEqualClientRule(metadata, context, description, validator));
});
@model Test.Models.PersonModel
@using (Html.BeginForm())
{
    @Html.TextBoxFor(x => x.First)
    @Html.ValidationMessageFor(x => x.First)
    @Html.TextBoxFor(x => x.Last)
    @Html.ValidationMessageFor(x => x.Last)
    <button type="submit">OK</button>
}
[Validator(typeof(PersonValidator))]
public class PersonModel
{
    public string First { get; set; }
    public string Last { get; set; }
}
public class PersonValidator : AbstractValidator<PersonModel>
{
    public PersonValidator()
    {
        RuleFor(x => x.First).NotEqual(x => x.Last);
    }
}

Gist

When I look back at it, the whole hash check bit in the js just feels icky, so I think I’d go back and fix it up – probably just check to see if the jQuery selector exists, and if so compare .val() otherwise just compare the value. Whatever, it works for now even if it isn’t perfect…