C# MVC 使用多个属性和 OR 条件

发布于 2024-11-16 19:40:42 字数 1118 浏览 6 评论 0原文

我的目标是创建一个经过验证的 IP 地址字段,该字段将根据常规表达的 IP 地址或动态 DNS 地址进行验证。因此,基本上,如果用户输入有效的 IP 地址或有效的动态 DNS 地址,客户端将允许其通过。我找到了一些文章,展示了如何创建自定义字段以及如何在数据字段上使用多个属性,但没有介绍如何将它们作为 OR 条件运行。

这是我的自定义 IP 和域名属性的代码:

    public class IPAddressAttribute : RegularExpressionAttribute
    {
        public IPAddressAttribute()
            : base(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
        { }
    }
    public class DomainNameAttribute : RegularExpressionAttribute
    {
        public DomainNameAttribute()
            : base(@"^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$")
        { }
    }

这是我的字段代码:

[Required(ErrorMessage="Wan IP is required")]
[DisplayName("Wan IP")]
[IPAddress(ErrorMessage="Enter a valid IP")]
[DomainName(ErrorMessage="Enter a valid Domain Name")]
public virtual string wan_ip { get; set; }

此代码当前检查这两个属性。当我输入有效的 IP 地址时,它返回说我需要输入有效的域名,这是可以理解的,因为它试图验证这两个属性。因为它们是相互排斥的,所以它们永远无法同时满足。

任何建议将不胜感激!

谢谢!

马修

My goal is to create a validated IP address field that will be validated against an IP address regular express or an dynamic DNS address. So basically if the user enters an valid IP address OR a valid dynamic DNS address the client will allow it to go through. I have found articles showing how to make custom fields and how to multiple attributes on a data field but nothing about how to run them as an OR condition.

Here is my code for the custom IP and Domain Name attributes:

    public class IPAddressAttribute : RegularExpressionAttribute
    {
        public IPAddressAttribute()
            : base(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
        { }
    }
    public class DomainNameAttribute : RegularExpressionAttribute
    {
        public DomainNameAttribute()
            : base(@"^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$")
        { }
    }

And here is my code for the field:

[Required(ErrorMessage="Wan IP is required")]
[DisplayName("Wan IP")]
[IPAddress(ErrorMessage="Enter a valid IP")]
[DomainName(ErrorMessage="Enter a valid Domain Name")]
public virtual string wan_ip { get; set; }

This code currently checks on both attributes. When I enter a valid IP address it comes back saying that I need to enter in a valid domain name, which is understandable because it's trying to validate on both of the attributes. Because they are mutually exclusive they can never both be satisfied.

Any suggestions will be greatly appreciated!

Thanks!

Matthew

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

策马西风 2024-11-23 19:40:42

我很确定您必须将它们合并到单个属性中,例如

[DomainOrIPAddress]

并在属性中处理您的 OR 逻辑。

或者您可以研究自定义模型验证器

I'm pretty sure you would have to merge them into a single Attribute, something like

[DomainOrIPAddress]

And handle your OR logic within the attribute.

Or you could look into custom Model Validators

感性 2024-11-23 19:40:42

您可以创建一个自定义验证属性,并使用其中的两个现有属性。 MSDN 上有一篇关于创建自定义属性的文章

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
sealed public class CustomAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        IPAddressAttribute a1 = new IPAddressAttribute();
        DomainNameAttribute a2 = new DomainNameAttribute();
        return a1.IsValid(value) || a2.IsValid(value);
    }    
}

You could create a custom validation attribute, and use the two existing ones inside it. There's an article on MSDN on creating custom attributes.

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
sealed public class CustomAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        IPAddressAttribute a1 = new IPAddressAttribute();
        DomainNameAttribute a2 = new DomainNameAttribute();
        return a1.IsValid(value) || a2.IsValid(value);
    }    
}
泼猴你往哪里跑 2024-11-23 19:40:42

使用 Jason 建议的策略,您还可以创建一个更通用的属性来处理“或”逻辑。我发现执行此操作的最佳方法是接收两个属性的类型,然后在内部激活它们(因为您对属性有很强的参数约束)。

用法:

[OneOfAttribute(typeof(IPAddressAttribute), typeof(DomainNameAttribute), ...)]

实现:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class OneOfAttribute : ValidationAttribute
{
    public ValidationAttribute[] Validators { get; set; }

    public OneOfAttribute(params Type[] validatorTypes)
    {
        Validators = validatorTypes.Select(Activator.CreateInstance)
            .OfType<ValidationAttribute>()
            .ToArray();

        // just to make sure this was correctly invoked
        if (validatorTypes.Length != Validators.Length)
        {
            throw new ArgumentException("Invalid validation attribute type");
        }
    }

    public override bool IsValid(object value)
    {
        return Validators.Any(v => v.IsValid(value));
    }
}

使用此策略,您还可以使其更加灵活,添加一个参数来指定将在 IsValid 方法上使用的逻辑运算(OR、AND 等)的类型。

Using the strategy that Jason suggested, you could also create a more generic attribute to handle the "Or" logic. The best way I've found to do this is to receive the Type of the two attributes and then activate them internally (since you have strong argument constraints on the attributes).

Usage:

[OneOfAttribute(typeof(IPAddressAttribute), typeof(DomainNameAttribute), ...)]

Implementation:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class OneOfAttribute : ValidationAttribute
{
    public ValidationAttribute[] Validators { get; set; }

    public OneOfAttribute(params Type[] validatorTypes)
    {
        Validators = validatorTypes.Select(Activator.CreateInstance)
            .OfType<ValidationAttribute>()
            .ToArray();

        // just to make sure this was correctly invoked
        if (validatorTypes.Length != Validators.Length)
        {
            throw new ArgumentException("Invalid validation attribute type");
        }
    }

    public override bool IsValid(object value)
    {
        return Validators.Any(v => v.IsValid(value));
    }
}

Using this strategy you could also make this even more flexible, adding an argument to specify the type of the logical operation (OR, AND, etc) that will the used on the IsValid method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文