c# - 不区分大小写比较的 CompareAttribute

标签 c# asp.net-mvc asp.net-mvc-3 c#-4.0

我在 MVC3 中使用 CompareAttribute 并且它工作正常。但我想使用不区分大小写的类代码。有什么方法可以让它工作吗

提前致谢

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

最佳答案

聚会有点晚了,但这是我刚刚编写的一个实现,它还包括使用 IClientValidatable 接口(interface)支持客户端验证。您也可以使用 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; }

这会插入非侵入式验证框架,因此您需要已经安装并运行该框架。在撰写本文时,我正在使用 Microsoft.jQuery.Unobtrusive.Validation v 3.0.0。

关于c# - 不区分大小写比较的 CompareAttribute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12822417/

相关文章:

c# - ASP.NET API Controller 的 POST 数据为空

c# - 使用结构而不是类的 EntityFramework SqlQuery 失败并出现 ArgumentException

c# - 找不到引用契约(Contract)的默认端点元素

asp.net-mvc - 复杂的强类型对象 + 默认 ModelBinder

javascript - 将带有 int 列表的对象从 jquery 发布到 .net mvc 3 Controller

asp.net-mvc-3 - 在 Kendo 网格中显示日期时间字段的空单元格值?

css - 打印 8.5x11 纸张格式的 html

c# - 独立运行 Silverlight 3

c# - WPF 使用 XAML 将 List<KeyValuePair<,>> 绑定(bind)到 DataGrid

asp.net - Umbraco 版本 5 出了什么问题?