5

我正在使用CompareAttributeinMVC3并且工作正常。但我想使用不区分大小写的类代码。有没有办法让它工作

提前致谢

[CompareAttribute("ClassCode", ErrorMessageResourceName = "ClassCode_DontMatch", ErrorMessageResourceType = typeof(Resources.Class))]
public string ConfirmClassCode {get; set; }
4

3 回答 3

10

IClientValidatable聚会有点晚了,但这是我刚刚编写的一个实现,它还包括对使用接口的客户端验证的支持。您也可以使用 Darin Dimitrov 的回答作为起点,我已经有了一些。

服务器端验证:

//Create your custom validation attribute
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class CompareStrings : ValidationAttribute, IClientValidatable
{
    private const string _defaultErrorMessage = "{0} must match {1}";

    public string OtherPropertyName { get; set; }

    public bool IgnoreCase { get; set; }

    public CompareStrings(string otherPropertyName)
        : base(_defaultErrorMessage)
    {
        if (String.IsNullOrWhiteSpace(otherPropertyName)) throw new ArgumentNullException("OtherPropertyName must be set.");

        OtherPropertyName = otherPropertyName;
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(ErrorMessage, name, OtherPropertyName);
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        string otherPropVal = validationContext.ObjectInstance.GetType().GetProperty(OtherPropertyName).GetValue(validationContext.ObjectInstance, null) as string;

        //Convert nulls to empty strings and trim spaces off the result
        string valString = (value as string ?? String.Empty).Trim();
        string otherPropValString = (otherPropVal ?? String.Empty).Trim();

        bool isMatch = String.Compare(valString, otherPropValString, IgnoreCase) == 0;

        if (isMatch)
            return ValidationResult.Success;
        else
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
    }

客户端验证

    //...continuation of CompareStrings class
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        return new[] { new ModelClientValidationCompareStringsRule(FormatErrorMessage(metadata.GetDisplayName()), OtherPropertyName, IgnoreCase) };
    }
}

定义 ModelClientValidationCompareStringsRule 用于(如上)将属性的属性传递给客户端脚本。

public class ModelClientValidationCompareStringsRule : ModelClientValidationRule
{
    public ModelClientValidationCompareStringsRule(string errorMessage, string otherProperty, bool ignoreCase)
    {
        ErrorMessage = errorMessage;  //The error message to display when invalid. Note we used FormatErrorMessage above to ensure this matches the server-side result.
        ValidationType = "comparestrings";    //Choose a unique name for your validator on the client side. This doesn't map to anything on the server side.
        ValidationParameters.Add("otherprop", otherProperty);  //Pass the name of the property to compare to
        ValidationParameters.Add("ignorecase", ignoreCase.ToString().ToLower());  //And whether to ignore casing
    }
}

Javascript:

(function ($) {
    //Add an adapter for our validator. This maps the data from the ModelClientValidationCompareStringsRule
    //we defined above, to the validation plugin. Make sure to use the same name as we chose for the ValidationType property ("comparestrings")
    $.validator.unobtrusive.adapters.add("comparestrings", ["otherprop", "ignorecase"],
        function (options) {
            options.rules["comparestrings"] = {
                otherPropName: options.params.otherprop,
                ignoreCase: options.params.ignorecase == "true"
            };
            options.messages["comparestrings"] = options.message;
        });

    //Add the method, again using the "comparestrings" name, that actually performs the client-side validation to the page's validator
    $.validator.addMethod("comparestrings", function (value, element, params) {
        //element is the element we are validating and value is its value

        //Get the MVC-generated prefix of element
        //(E.G. "MyViewModel_" from id="MyViewModel_CompareEmail"
        var modelPrefix = getModelIDPrefix($(element).prop("id"));

        //otherPropName is just the name of the property but we need to find
        //its associated element to get its value. So concatenate element's
        //modelPrefix with the other property name to get the full MVC-generated ID. If your elements use your own, overridden IDs, you'd have to make some modifications to allow this code to find them (e.g. finding by the name attribute)
        var $otherPropElem = $("#" + modelPrefix + params.otherPropName);

        var otherPropValue = getElemValue($otherPropElem);

        //Note: Logic for comparing strings needs to match what it does on the server side

        //Trim values
        value = $.trim(value);
        otherPropValue = $.trim(otherPropValue);

        //If ignoring case, lower both values
        if (params.ignoreCase) {
            value = value.toLowerCase();
            otherPropValue = otherPropValue.toLowerCase();
        }

        //compare the values
        var isMatch = value == otherPropValue;

        return isMatch;
    });

    function getElemValue(element){
        var value;
        var $elem = $(element);

        //Probably wouldn't use checkboxes or radio buttons with
        //comparestrings, but this method can be used for other validators too
        if($elem.is(":checkbox") || $elem.is(":radio") == "radio")
            value = $elem.prop("checked") ? "true" : "false";
        else
            value = $elem.val();

        return value;
    }

    //Gets the MVC-generated prefix for a field by returning the given string
    //up to and including the last underscore character
    function getModelIDPrefix(fieldID) {
        return fieldID.substr(0, fieldID.lastIndexOf("_") + 1);
    }
}(jQuery));

用法是标准的:

public string EmailAddress { get; set; }

[CompareStrings("EmailAddress", ErrorMessage = "The email addresses do not match", IgnoreCase=true)]
public string EmailAddressConfirm { get; set; }

这插入了 Unobtrusive Validation 框架,因此您需要已经安装并工作。在撰写本文时,我使用的是 Microsoft.jQuery.Unobtrusive.Validation v 3.0.0。

于 2015-10-29T19:31:43.807 回答
8

您可以编写一个自定义属性来执行不区分大小写的比较:

public class CaseInsensitiveCompareAttribute : System.Web.Mvc.CompareAttribute
{
    public CaseInsensitiveCompareAttribute(string otherProperty)
        : base(otherProperty)
    { }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(this.OtherProperty);
        if (property == null)
        {
            return new ValidationResult(string.Format(CultureInfo.CurrentCulture, "Unknown property {0}", this.OtherProperty));
        }
        var otherValue = property.GetValue(validationContext.ObjectInstance, null) as string;
        if (string.Equals(value as string, otherValue, StringComparison.OrdinalIgnoreCase))
        {
            return null;
        }

        return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
    }
}

然后用它装饰你的视图模型属性:

[CaseInsensitiveCompare("ClassCode", ErrorMessageResourceName = "ClassCode_DontMatch", ErrorMessageResourceType = typeof(Resources.Class))]
public string ConfirmClassCode { get; set; }
于 2012-10-10T15:04:51.967 回答
0

对于客户端验证,将此代码放在下面的文档中 -

jQuery.validator.addMethod("ignoredCaseEqualTo", function (value, element, param) {
            return this.optional(element) || value.toLowerCase() === $(param).val().toLowerCase();
        }, "__Your Validation message___");

        $("#EmailAddress").rules("add", {
            ignoredCaseEqualTo: "#EmailAddressConfirm"
        });

此代码添加了不区分大小写比较的新验证规则。可能不是最佳方式,但这将完成您的客户端验证工作。

于 2018-05-15T05:03:29.927 回答