MVC.NET Core 中的条件验证(RequiredIf)

我正在尝试有条件地验证 MVC.NET Core 中的字段。我有两个单选按钮。如果我选择是(对于所有权),我想在下面填写一个必填字段(活动下拉菜单)


但是,无论我如何努力,要验证的值始终来自 Activity 字段,而不是来自 Ownership 字段(“N\A”而不是“Yes”)


有人可以告诉我我做错了什么吗


视图 (chtml)


<div class=" form-group">

    <div class="bisformdynamiclabel"></div>

    <br />

    @Html.RadioButtonFor(model => model.BIS232Request.JSONData.OwnershipActivity.Ownership, "Yes", new { id = "OwnershipAnswer_true", onclick = "displayOwnershipFieldsRow(true)" })

    <label for="OwnershipAnswer_true">Yes</label>

    @Html.RadioButtonFor(model => model.BIS232Request.JSONData.OwnershipActivity.Ownership, "No", new { id = "OwnershipAnswer_false", onclick = "displayOwnershipFieldsRow(false)" })

    <label for="OwnershipAnswer_false">No</label>

    <span class="alert-danger">

        @Html.ValidationMessage("OwnershipAnswer")

    </span>

</div>

<div class="row ownershipfieldsrow">

    <div class="col-xs-12 col-md-12">

        <div class=" form-group">

            <div class="bisformdynamiclabel"></div>

            <br />

            <input style="display:none" class="form-control" type="text" asp-for="BIS232Request.JSONData.OwnershipActivity.Activity" />

            <select class="form-control ownershipactivityselect" onchange="$('#BIS232Request_JSONData_OwnershipActivity_Activity').val($(this).val());  ">

                <option value="N/A">Please Select</option>

                <option value="Manufacturer">Manufacturer</option>

                <option value="Distributor">Distributor</option>

                <option value="Exporter">Exporter</option>

                <option value="Importer">Importer</option>

                <option value="Other">Other</option>

            </select>

            <span asp-validation-for="BIS232Request.JSONData.OwnershipActivity.Activity" class="alert-danger"></span>

            <span class="alert-danger">

                @Html.ValidationMessage("OwnershipAnswerActivity")

            </span>

        </div>

    </div>

隔江千里
浏览 624回答 3
3回答

慕妹3146593

基于最初的实现,我建议扩展RequiredAttribute而不是ValidationAttribute- 然后根据 [Required] 设置默认的 ErrorMessage 和其他默认值。无论哪种方式,“errormessage”属性都是多余的,因为您已经将其作为属性,ValidationAttribute并且原始代码会为该属性生成警告ErrorMessage- 您也可以将nameof其用于属性装饰,以使代码中的内容更加紧凑:我的实现稍微更具体一些,因此如果一个属性是布尔值,我可以指示一个属性是必需的(如果勾选了一个复选框):[AttributeUsage(AttributeTargets.Property)]public class RequiredIfTrueAttribute : RequiredAttribute{&nbsp; &nbsp; private string PropertyName { get; set; }&nbsp; &nbsp; public RequiredIfTrueAttribute(string propertyName)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; PropertyName = propertyName;&nbsp; &nbsp; }&nbsp; &nbsp; protected override ValidationResult IsValid(object value, ValidationContext context)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; object instance = context.ObjectInstance;&nbsp; &nbsp; &nbsp; &nbsp; Type type = instance.GetType();&nbsp; &nbsp; &nbsp; &nbsp; bool.TryParse(type.GetProperty(PropertyName).GetValue(instance)?.ToString(), out bool propertyValue);&nbsp; &nbsp; &nbsp; &nbsp; if (propertyValue && string.IsNullOrWhiteSpace(value?.ToString()))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new ValidationResult(ErrorMessage);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return ValidationResult.Success;&nbsp; &nbsp; }}示例用法:public bool IsBusinessProfile { get; set; }[RequiredIfTrue(nameof(IsBusinessProfile), ErrorMessage = "ABN is required for Business Profiles")]public string Abn { get; set; }

拉丁的传说

我建立在 Rob 提供的答案之上。这是一个通用验证器,而不是继承自Required,并且还提供客户端验证。我正在使用.Net Core 3.0using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;using System;using System.Collections.Generic;using System.Text;namespace System.ComponentModel.DataAnnotations{&nbsp; &nbsp; [AttributeUsage(AttributeTargets.Property)]&nbsp; &nbsp; public class RequiredIfTrueAttribute : ValidationAttribute, IClientModelValidator&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; private string PropertyName { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public RequiredIfTrueAttribute(string propertyName)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PropertyName = propertyName;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ErrorMessage = "The {0} field is required."; //used if error message is not set on attribute itself&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; protected override ValidationResult IsValid(object value, ValidationContext context)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; object instance = context.ObjectInstance;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type type = instance.GetType();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bool.TryParse(type.GetProperty(PropertyName).GetValue(instance)?.ToString(), out bool propertyValue);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (propertyValue && (value == null || string.IsNullOrWhiteSpace(value.ToString())))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new ValidationResult(ErrorMessage);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ValidationResult.Success;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public void AddValidation(ClientModelValidationContext context)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MergeAttribute(context.Attributes, "data-val", "true");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MergeAttribute(context.Attributes, "data-val-requirediftrue", errorMessage);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (attributes.ContainsKey(key))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; attributes.Add(key, value);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}客户端 Javascript//Custom validation script for the RequiredIfTrue validator/*&nbsp;* Note that, jQuery validation registers its rules before the DOM is loaded.&nbsp;&nbsp;* If you try to register your adapter after the DOM is loaded, your rules will&nbsp;* not be processed. So wrap it in a self-executing function.&nbsp;* */(function ($) {&nbsp; &nbsp; var $jQval = $.validator;&nbsp; &nbsp;$jQval.addMethod("requirediftrue",&nbsp; &nbsp; &nbsp; &nbsp;function (value, element, parameters) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return value !== "" && value != null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; );&nbsp; &nbsp; var adapters = $jQval.unobtrusive.adapters;&nbsp; &nbsp; adapters.addBool('requirediftrue');})(jQuery);用法&nbsp; &nbsp; public bool IsSpecialField { get; set; }&nbsp; &nbsp; [RequiredIfTrue(nameof(IsSpecialField), ErrorMessage="This is my custom error message")]&nbsp; &nbsp; [Display(Name = "Address 1")]&nbsp; &nbsp; public string Address1 { get; set; }&nbsp; &nbsp; [RequiredIfTrue(nameof(IsSpecialField))]&nbsp; &nbsp; public string City { get; set; }

侃侃尔雅

另一种更简洁、更通用的方法是实现更通用的属性,而不是特定的“requiredIf”属性,因为您必须为碰巧使用的每种验证类型创建多个自定义属性。幸运的是,从 .NET Core 2 开始,Microsoft 提供了IPropertyValidationFilter可以在自定义属性上实现的接口。这个接口定义了一个函数ShouldValidateEntry,它允许控制当前条目是否应该被验证;所以这在调用任何验证器之前运行。框架中已经有一个默认实现,即ValidateNeverAttribute,但是实现您自己的对另一个值进行条件检查是微不足道的:using System;using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;namespace Foo {&nbsp; &nbsp; // Implementation makes use of the IPropertyValidationFilter interface that allows&nbsp; &nbsp; // control over whether the attribute (and its children, if relevant) need to be&nbsp; &nbsp; // validated.&nbsp; &nbsp; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]&nbsp; &nbsp; public class ConditionalValidationAttribute : Attribute, IPropertyValidationFilter {&nbsp; &nbsp; &nbsp; &nbsp; public string OtherProperty { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public object OtherValue { get; set; }&nbsp; &nbsp; &nbsp; &nbsp; public ConditionalValidationAttribute(string otherProperty, object otherValue) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OtherProperty = otherProperty;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OtherValue = otherValue;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public bool ShouldValidateEntry(ValidationEntry entry, ValidationEntry parentEntry) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Default behaviour if no other property is set: continue validation&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (string.IsNullOrWhiteSpace(OtherProperty)) return true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Get the property specified by the name. Might not properly work with&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // nested properties.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var prop = parentEntry.Metadata.Properties[OtherProperty]?.PropertyGetter?.Invoke(parentEntry.Model);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return prop == OtherValue;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}只需使用此属性注释相关属性,任何验证器,以及您自己实现的自定义验证器,只会在必要时调用!
打开App,查看更多内容
随时随地看视频慕课网APP