gpt4 book ai didi

c# - 使用 ASP.NET MVC 4 在运行时动态应用验证规则

转载 作者:太空狗 更新时间:2023-10-29 20:04:48 28 4
gpt4 key购买 nike

多年来我一直在使用 WebForms,但我对 .NET 风格的 MVC 还很陌生。我试图弄清楚如何在运行时将动态验证规则应用于我的模型成员。出于这个问题的目的,这些是我正在使用的类的简化版本:

public class Device
{
public int Id {get; set;}
public ICollection<Setting> Settings {get; set;}
}

public class Setting
{
public int Id {get; set;}
public string Value {get; set;}
public bool IsRequired {get; set;}
public int MinLength {get; set;}
public int MaxLength {get; set;}
}

在我看来,我将使用每个编辑器遍历设置集合,并在运行时应用每个设置实例中包含的验证规则,以实现与我在模型上使用 DataAnnotations 获得的相同的客户端和服务器端验证编译时。在 WebForms 中,我只是将适当的验证器附加到相关字段,但我在 MVC4 中找不到类似的机制时遇到了麻烦。有办法实现吗?

最佳答案

我的解决方案是扩展 ValidationAttribute 类并实现 IClientValidatable 接口(interface)。下面是一个完整的例子,还有一些改进的余地:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Web.Mvc;

namespace WebApplication.Common
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class RuntimeRequiredAttribute : ValidationAttribute, IClientValidatable
{
public string BooleanSwitch { get; private set; }
public bool AllowEmptyStrings { get; private set; }

public RuntimeRequiredAttribute(string booleanSwitch = "IsRequired", bool allowEmpytStrings = false ) : base("The {0} field is required.")
{
BooleanSwitch = booleanSwitch;
AllowEmptyStrings = allowEmpytStrings;
}

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
PropertyInfo property = validationContext.ObjectType.GetProperty(BooleanSwitch);

if (property == null || property.PropertyType != typeof(bool))
{
throw new ArgumentException(
BooleanSwitch + " is not a valid boolean property for " + validationContext.ObjectType.Name,
BooleanSwitch);
}

if ((bool) property.GetValue(validationContext.ObjectInstance, null) &&
(value == null || (!AllowEmptyStrings && value is string && String.IsNullOrWhiteSpace(value as string))))
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}

return ValidationResult.Success;
}

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata,
ControllerContext context)
{
object model = context.Controller.ViewData.Model;
bool required = (bool)model.GetType().GetProperty(BooleanSwitch).GetValue(model, null);

if (required)
{
yield return
new ModelClientValidationRequiredRule(
FormatErrorMessage(metadata.DisplayName ?? metadata.PropertyName));
}
else
//we have to return a ModelCLientValidationRule where
//ValidationType is not empty or else we get an exception
//since we don't add validation rules clientside for 'notrequired'
//no validation occurs and this works, though it's a bit of a hack
{
yield return
new ModelClientValidationRule {ValidationType = "notrequired", ErrorMessage = ""};
}
}
}
}

上面的代码将在模型上寻找一个属性以用作验证的开关(IsRequired 是默认值)。如果要用作开关的 bool 属性设置为 true,则客户端和服务器端验证都会对用 RuntimeRequiredValdiationAttribute 修饰的属性执行。重要的是要注意,此类假定用于验证开关的模型的任何属性都不会显示给最终用户进行编辑,即这不是 RequiredIf 验证器。

实际上还有另一种方法可以实现 ValidationAttribute 以及客户端验证 as outlined here .为了比较,我上面所做的 IClientValidatable 路由是 outlined by the same author here .

请注意这目前不适用于嵌套对象,例如,如果该属性装饰了另一个对象包含的对象的属性,则它不会起作用。有一些选项可以解决这个缺点,但到目前为止,我还没有必要。

关于c# - 使用 ASP.NET MVC 4 在运行时动态应用验证规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18919758/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com