Mik*_*ail 13 c# asp.net-core-mvc
我正在尝试有条件地验证 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>
Run Code Online (Sandbox Code Playgroud)
该模型
[Required]
public string Ownership { get; set; }
[RequiredIf("Ownership", "OwnershipAnswer_true", "Activity is required if Ownership is selected")]
public string Activity { get; set; }
public class RequiredIfAttribute : ValidationAttribute
{
private String PropertyName { get; set; }
private String ErrorMessage { get; set; }
private Object DesiredValue { get; set; }
public RequiredIfAttribute(String propertyName, Object desiredvalue, String errormessage)
{
this.PropertyName = propertyName;
this.DesiredValue = desiredvalue;
this.ErrorMessage = errormessage;
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
Object instance = context.ObjectInstance;
Type type = instance.GetType();
Object proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
if (proprtyvalue.ToString() == DesiredValue.ToString() && value == null)
{
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
}
Run Code Online (Sandbox Code Playgroud)
基于原始实现,我建议扩展RequiredAttribute而不是ValidationAttribute- 然后根据 [Required] 设置您的默认 ErrorMessage 和其他默认值。无论哪种方式,“errormessage”属性都是多余的,因为您已经将其作为属性,ValidationAttribute并且原始代码为该ErrorMessage属性生成警告- 您也可以nameof用于属性装饰以及使代码中的内容更加紧密:
我的实现稍微更具体,因此如果属性是 bool,我可以指示需要一个属性(如果说勾选了复选框):
[AttributeUsage(AttributeTargets.Property)]
public class RequiredIfTrueAttribute : RequiredAttribute
{
private string PropertyName { get; set; }
public RequiredIfTrueAttribute(string propertyName)
{
PropertyName = propertyName;
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
object instance = context.ObjectInstance;
Type type = instance.GetType();
bool.TryParse(type.GetProperty(PropertyName).GetValue(instance)?.ToString(), out bool propertyValue);
if (propertyValue && string.IsNullOrWhiteSpace(value?.ToString()))
{
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
}
Run Code Online (Sandbox Code Playgroud)
示例用法:
public bool IsBusinessProfile { get; set; }
[RequiredIfTrue(nameof(IsBusinessProfile), ErrorMessage = "ABN is required for Business Profiles")]
public string Abn { get; set; }
Run Code Online (Sandbox Code Playgroud)
我以 Rob 提供的答案为基础。这是一个通用验证器,而不是从 继承Required,并且还提供客户端验证。我正在使用 .Net Core 3.0
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System;
using System.Collections.Generic;
using System.Text;
namespace System.ComponentModel.DataAnnotations
{
[AttributeUsage(AttributeTargets.Property)]
public class RequiredIfTrueAttribute : ValidationAttribute, IClientModelValidator
{
private string PropertyName { get; set; }
public RequiredIfTrueAttribute(string propertyName)
{
PropertyName = propertyName;
ErrorMessage = "The {0} field is required."; //used if error message is not set on attribute itself
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
object instance = context.ObjectInstance;
Type type = instance.GetType();
bool.TryParse(type.GetProperty(PropertyName).GetValue(instance)?.ToString(), out bool propertyValue);
if (propertyValue && (value == null || string.IsNullOrWhiteSpace(value.ToString())))
{
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
MergeAttribute(context.Attributes, "data-val-requirediftrue", errorMessage);
}
private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
{
if (attributes.ContainsKey(key))
{
return false;
}
attributes.Add(key, value);
return true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
客户端 Javascript
//Custom validation script for the RequiredIfTrue validator
/*
* Note that, jQuery validation registers its rules before the DOM is loaded.
* If you try to register your adapter after the DOM is loaded, your rules will
* not be processed. So wrap it in a self-executing function.
* */
(function ($) {
var $jQval = $.validator;
$jQval.addMethod("requirediftrue",
function (value, element, parameters) {
return value !== "" && value != null;
}
);
var adapters = $jQval.unobtrusive.adapters;
adapters.addBool('requirediftrue');
})(jQuery);
Run Code Online (Sandbox Code Playgroud)
用法
public bool IsSpecialField { get; set; }
[RequiredIfTrue(nameof(IsSpecialField), ErrorMessage="This is my custom error message")]
[Display(Name = "Address 1")]
public string Address1 { get; set; }
[RequiredIfTrue(nameof(IsSpecialField))]
public string City { get; set; }
Run Code Online (Sandbox Code Playgroud)
找到了答案
改变了
if (proprtyvalue.ToString() == DesiredValue.ToString() && value == null)
Run Code Online (Sandbox Code Playgroud)
到
if (proprtyvalue.ToString() == DesiredValue.ToString() && value.ToString() == "N/A")
Run Code Online (Sandbox Code Playgroud)