Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何基于所选国家/地区,在MVC3中编写用于美国或加拿大邮政编码验证的自定义验证器?_C#_Jquery_Asp.net Mvc 3_Validation - Fatal编程技术网

C# 如何基于所选国家/地区,在MVC3中编写用于美国或加拿大邮政编码验证的自定义验证器?

C# 如何基于所选国家/地区,在MVC3中编写用于美国或加拿大邮政编码验证的自定义验证器?,c#,jquery,asp.net-mvc-3,validation,C#,Jquery,Asp.net Mvc 3,Validation,我需要对帐单地址字段应用自定义验证器。该视图显示多个地址字段,包括国家/地区下拉列表(带有美国和加拿大选项)和BillingPostalCode文本框。最初,我将正则表达式应用于允许美国或加拿大邮政编码的消息契约,如下所示: [MessageBodyMember] [Display(Name = "Billing Postal Code")] [Required] [StringLength(10, MinimumLength = 5)] [RegularExpression("(^\\d{5}

我需要对帐单地址字段应用自定义验证器。该视图显示多个地址字段,包括国家/地区下拉列表(带有美国和加拿大选项)和BillingPostalCode文本框。最初,我将正则表达式应用于允许美国或加拿大邮政编码的消息契约,如下所示:

[MessageBodyMember]
[Display(Name = "Billing Postal Code")]
[Required]
[StringLength(10, MinimumLength = 5)]
[RegularExpression("(^\\d{5}(-\\d{4})?$)|(^[ABCEGHJKLMNPRSTVXY]{1}\\d{1}[A-Z]{1} *\\d{1}[A-Z]{1}\\d{1}$)", ErrorMessage = "Zip code is invalid.")] // US or Canada
public string BillingPostalCode
{
   get { return _billingPostalCode; }
   set { _billingPostalCode = value; }
}
上述内容将允许使用美国或加拿大邮政编码。但是,业务所有者希望表单仅在BillingCountry下拉列表中分别选择美国或加拿大时才允许使用美国或加拿大邮政编码。在他的测试案例中,他选择了加拿大并输入了美国邮政编码。这种情况应该被禁止

我最初尝试这样做是为了把它放到视图中,尽管我不喜欢创建两个文本框字段。我应该只需要一个字段

<div style="float: left; width: 35%;">
   Zip Code<br />
   <span id="spanBillingZipUS">
      @Html.TextBoxFor(m => m.BillingPostalCode, new { @class = "customer_input", @id = "BillingPostalCode" })
   </span>
   <span id="spanBillingZipCanada">
      @Html.TextBoxFor(m => m.BillingPostalCode, new { @class = "customer_input", @id = "BillingPostalCodeCanada" })
   </span>
   @Html.ValidationMessageFor(m => m.BillingPostalCode)
   <br />
</div>

邮政编码
@TextBoxFor(m=>m.BillingPostalCode,新的{@class=“customer\u input”,@id=“BillingPostalCode”}) @TextBoxFor(m=>m.BillingPostalCode,新的{@class=“customer_input”,@id=“BillingPostalCodeCanada”}) @Html.ValidationMessageFor(m=>m.BillingPostalCode)
我的想法是,当切换国家下拉列表时,我将使用jQuery显示或隐藏适当的范围。那件很容易

但我遇到的问题是,两个文本框都应用了单个验证器,该验证器映射到上面粘贴的MessageBodyMember。我知道如何在jQuery中编写验证代码,但更希望将验证应用到服务器端

我是MVC的新手,来自web表单。“老式”web表单自定义验证易于实现。我在网上找到的MVC自定义验证示例非常复杂。起初,这似乎是一个非常基本的要求。代码需要计算一个变量(所选国家/地区),并将该国家/地区的适当正则表达式应用于BillingPostalCode字段

如何使用MVC3以简单的方式满足此要求?谢谢。

我实现了什么,它作为带有数据注释的chram工作。为了更改下拉值的检查,您确实需要做一些工作,但这是我发现的用数据注释和不引人注目的实现验证的更优雅的方法


这里有一个例子:

模型 自定义属性
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Web;
使用System.ComponentModel.DataAnnotations;
使用System.Web.Mvc;
命名空间Mvc3ConditionalValidation.Validation
{
公共类requireditAttribute:ValidationAttribute,IClientValidable
{
私有RequiredAttribute_innerAttribute=新RequiredAttribute();
公共字符串依赖属性{get;set;}
公共对象TargetValue{get;set;}
public requirediftAttribute(字符串相关属性,对象targetValue)
{
this.DependentProperty=DependentProperty;
this.TargetValue=TargetValue;
}
受保护的重写ValidationResult有效(对象值,ValidationContext ValidationContext)
{
//获取对此验证所依赖的属性的引用
var containerType=validationContext.ObjectInstance.GetType();
var field=containerType.GetProperty(this.DependentProperty);
如果(字段!=null)
{
//获取依赖属性的值
var dependentvalue=field.GetValue(validationContext.ObjectInstance,null);
//将该值与目标值进行比较
if((dependentvalue==null&&this.TargetValue==null)||
(dependentvalue!=null&&dependentvalue.Equals(this.TargetValue)))
{
//match=>表示我们应该尝试验证此字段
如果(!\u innerAttribute.IsValid(值))
//验证失败-返回错误
返回新的ValidationResult(this.ErrorMessage,new[]{validationContext.MemberName});
}
}
返回ValidationResult.Success;
}
公共IEnumerable GetClientValidationRules(ModelMetadata元数据、ControllerContext上下文)
{
var rule=new ModelClientValidationRule()
{
ErrorMessage=FormatErrorMessage(metadata.GetDisplayName()),
ValidationType=“requiredif”,
};
string depProp=BuildDependentPropertyId(元数据,上下文为ViewContext);
//找到我们所依赖的控件的值;
//如果是bool,则将其格式化为javascript样式
//(默认值为True或False!)
字符串targetValue=(this.targetValue???).ToString();
if(this.TargetValue.GetType()==typeof(bool))
targetValue=targetValue.ToLower();
rule.ValidationParameters.Add(“dependentproperty”,depProp);
规则.ValidationParameters.Add(“targetvalue”,targetvalue);
收益率-收益率规则;
}
私有字符串BuildDependentPropertyId(ModelMetadata元数据,ViewContext)
{
//生成属性的ID
string depProp=viewContext.ViewData.TemplateInfo.GetFullHtmlFieldDid(this.DependentProperty);
//不幸的是,这将在开头追加当前字段的名称,
//因为TemplateInfo的上下文已经附加了这个字段名
//想要获得更高一级的上下文(即在当前属性之外,
//哪一个是包含对象(我们的人)
...
        [RequiredIf("IsUKResident", true, ErrorMessage = "You must specify the City if UK resident")]
        public string City { get; set; }
...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace Mvc3ConditionalValidation.Validation
{
    public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
    {
        private RequiredAttribute _innerAttribute = new RequiredAttribute();

        public string DependentProperty { get; set; }
        public object TargetValue { get; set; }

        public RequiredIfAttribute(string dependentProperty, object targetValue)
        {
            this.DependentProperty = dependentProperty;
            this.TargetValue = targetValue;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            // get a reference to the property this validation depends upon
            var containerType = validationContext.ObjectInstance.GetType();
            var field = containerType.GetProperty(this.DependentProperty);

            if (field != null)
            {
                // get the value of the dependent property
                var dependentvalue = field.GetValue(validationContext.ObjectInstance, null);

                // compare the value against the target value
                if ((dependentvalue == null && this.TargetValue == null) ||
                    (dependentvalue != null && dependentvalue.Equals(this.TargetValue)))
                {
                    // match => means we should try validating this field
                    if (!_innerAttribute.IsValid(value))
                        // validation failed - return an error
                        return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
                }
            }

            return ValidationResult.Success;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule()
            {
                ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                ValidationType = "requiredif",
            };

            string depProp = BuildDependentPropertyId(metadata, context as ViewContext);

            // find the value on the control we depend on;
            // if it's a bool, format it javascript style 
            // (the default is True or False!)
            string targetValue = (this.TargetValue ?? "").ToString();
            if (this.TargetValue.GetType() == typeof(bool))
                targetValue = targetValue.ToLower();

            rule.ValidationParameters.Add("dependentproperty", depProp);
            rule.ValidationParameters.Add("targetvalue", targetValue);

            yield return rule;
        }

        private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
        {
            // build the ID of the property
            string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(this.DependentProperty);
            // unfortunately this will have the name of the current field appended to the beginning,
            // because the TemplateInfo's context has had this fieldname appended to it. Instead, we
            // want to get the context as though it was one level higher (i.e. outside the current property,
            // which is the containing object (our Person), and hence the same level as the dependent property.
            var thisField = metadata.PropertyName + "_";
            if (depProp.StartsWith(thisField))
                // strip it off again
                depProp = depProp.Substring(thisField.Length);
            return depProp;
        }
    }
}
...
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

<script>
    $.validator.addMethod('requiredif',
        function (value, element, parameters) {
            var id = '#' + parameters['dependentproperty'];

            // get the target value (as a string, 
            // as that's what actual value will be)
            var targetvalue = parameters['targetvalue'];
            targetvalue = 
              (targetvalue == null ? '' : targetvalue).toString();

            // get the actual value of the target control
            // note - this probably needs to cater for more 
            // control types, e.g. radios
            var control = $(id);
            var controltype = control.attr('type');
            var actualvalue =
                controltype === 'checkbox' ?
                control.attr('checked').toString() :
                control.val();

            // if the condition is true, reuse the existing 
            // required field validator functionality
            if (targetvalue === actualvalue)
                return $.validator.methods.required.call(
                  this, value, element, parameters);

            return true;
        }
    );

    $.validator.unobtrusive.adapters.add(
        'requiredif',
        ['dependentproperty', 'targetvalue'], 
        function (options) {
            options.rules['requiredif'] = {
                dependentproperty: options.params['dependentproperty'],
                targetvalue: options.params['targetvalue']
            };
            options.messages['requiredif'] = options.message;
        });

</script>
...
    <div class="editor-label">
        @Html.LabelFor(model => model.City)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.City)
        @Html.ValidationMessageFor(model => model.City)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.IsUKResident)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.IsUKResident)
        @Html.ValidationMessageFor(model => model.IsUKResident)
    </div>
...
[Post]
public ActionResult SaveInfo(MyViewModel viewModel)
{
    var isValid = true;
    if (ModelState.IsValid)
    {
        if (!IsValidPostCode(viewModel))
        {
            isValid = false;
            ModelState.AddModelError("BillingPostalCode", "The billing postcode appears to be invalid.");
        }

        if (isValid)
        {
            return RedirectToAction("success");
        }
    }

    return View(viewModel);
}

private static IDictionary<string, string> countryPostCodeRegex = new Dictionary<string, string>
    {
        { "USA", "USAPostCodeRegex" },
        { "Canada", "CanadianPostCodeRegex" },
    }

private bool IsValidPostCode(MyViewModel viewModel)
{
    var regexString = countryPostCodeRegex[viewModel.SelectedCountry];
    var regexMatch = Regex.Match(viewModel.BillingPostalCode, regexString, RegexOptions.IgnoreCase);

    return regexMatch.Success;
}
[RequiredIf(DependentName = "Country", DependentValue="USA")]
public string PostalCodeUSA { get; set; }

[RequiredIf(DependentName = "Country", DependentValue="Canada")]
public string PostalCodeCanada { get; set; }