C# ASP.NET核心验证:动态关闭某些属性的服务器验证
是否有一种方法可以基于绑定模型值关闭某些模型属性的验证。 例如: 这是一个视图模型,它应该检索此人的姓名,以及他的电话或电子邮件。如果用户选择其中一个,它应该只验证所选的一个。但当选择Phone且电子邮件为空时,C# ASP.NET核心验证:动态关闭某些属性的服务器验证,c#,asp.net-core,model-validation,C#,Asp.net Core,Model Validation,是否有一种方法可以基于绑定模型值关闭某些模型属性的验证。 例如: 这是一个视图模型,它应该检索此人的姓名,以及他的电话或电子邮件。如果用户选择其中一个,它应该只验证所选的一个。但当选择Phone且电子邮件为空时,ModelState.IsValid==false,反之亦然 我曾尝试连接到验证过程(自定义ValidationAttribute,IValidatableObject),但没有成功,因为ValidationContext没有提供任何有用的上下文-在验证电话/电子邮件时,我需要访问联系人
ModelState.IsValid==false,反之亦然
我曾尝试连接到验证过程(自定义ValidationAttribute
,IValidatableObject
),但没有成功,因为ValidationContext没有提供任何有用的上下文-在验证电话/电子邮件时,我需要访问联系人类型
值。我甚至尝试创建自定义绑定,但在该阶段取消验证并不能提供预期结果,因为它只会将验证状态设置为未验证,这被视为ModelState.IsValid
到目前为止,我找到的唯一解决方案是创建ActionFilter/PageFilter
,它将查找是否存在ContactModel
类型的任何模型,并从ModelState中删除未使用字段的验证错误。但我对这样的解决方案感到不舒服(在我看来不合适)。
有什么想法吗? < P>根据您的描述,我建议您可以考虑使用自定义CuoMealValueAudio和自定义模型验证器来实现您的要求。
通过使用它,我们可以使用它的容器值得到整个模型
更多详细信息,请参考以下代码:
CustomModelValidator提供程序类:
public void CreateValidators(ModelValidatorProviderContext context)
{
if (context.ModelMetadata.ContainerType == typeof(ContactModel))
{
context.Results.Add(new ValidatorItem
{
Validator = new ContactModelValidator(),
IsReusable = true
});
}
}
public class ContactModelValidator : IModelValidator
{
private static readonly object _emptyValidationContextInstance = new object();
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext validationContext)
{
var validationResults = new List<ModelValidationResult>();
if (validationContext.ModelMetadata.Name == "Name" && validationContext.Model == null)
{
var validationResult = new ModelValidationResult("", "Name is required");
validationResults.Add(validationResult);
}
if (validationContext.ModelMetadata.Name == "ContactType" && validationContext.Model == null)
{
var validationResult = new ModelValidationResult("", "ContactType is required");
validationResults.Add(validationResult);
}
if (validationContext.ModelMetadata.Name == "ContactType" && validationContext.Model == null)
{
var validationResult = new ModelValidationResult("", "ContactType is required");
validationResults.Add(validationResult);
}
if (validationContext.ModelMetadata.Name == "Phone" || validationContext.ModelMetadata.Name == "Email")
{
if (((ContactModel)validationContext.Container).Phone == null && ((ContactModel)validationContext.Container).Email == null)
{
var validationResult = new ModelValidationResult("", "Phone or Email is required");
validationResults.Add(validationResult);
}
}
return validationResults;
}
}
结果:
有更新吗?我的回答对你有帮助吗?虽然有效,但我不能接受它作为回答。通过在ContactModel
中实现IValidatableObject
并检查模型的实际值,可以更轻松地完成上述操作。但这是我的错——在追求尽可能简单的过程中,我选择了简单的例子。事实上,我的模型有一些列表和泛型参数,这使得这个方法毫无用处。我必须找到不同的方法-在自定义模型绑定期间(无论如何我都必须这么做),我操作validationstatentry
,它禁用子模型选定部分的验证+1无论如何。
public void CreateValidators(ModelValidatorProviderContext context)
{
if (context.ModelMetadata.ContainerType == typeof(ContactModel))
{
context.Results.Add(new ValidatorItem
{
Validator = new ContactModelValidator(),
IsReusable = true
});
}
}
public class ContactModelValidator : IModelValidator
{
private static readonly object _emptyValidationContextInstance = new object();
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext validationContext)
{
var validationResults = new List<ModelValidationResult>();
if (validationContext.ModelMetadata.Name == "Name" && validationContext.Model == null)
{
var validationResult = new ModelValidationResult("", "Name is required");
validationResults.Add(validationResult);
}
if (validationContext.ModelMetadata.Name == "ContactType" && validationContext.Model == null)
{
var validationResult = new ModelValidationResult("", "ContactType is required");
validationResults.Add(validationResult);
}
if (validationContext.ModelMetadata.Name == "ContactType" && validationContext.Model == null)
{
var validationResult = new ModelValidationResult("", "ContactType is required");
validationResults.Add(validationResult);
}
if (validationContext.ModelMetadata.Name == "Phone" || validationContext.ModelMetadata.Name == "Email")
{
if (((ContactModel)validationContext.Container).Phone == null && ((ContactModel)validationContext.Container).Email == null)
{
var validationResult = new ModelValidationResult("", "Phone or Email is required");
validationResults.Add(validationResult);
}
}
return validationResults;
}
}
services.AddControllers(options=> {
options.ModelValidatorProviders.Add(new CustomModelValidatorProvider());
});