简体   繁体   English

可选地将必填字段与 ASP.NET MVC 数据注释一起使用

[英]Using Required field optionally with ASP.NET MVC Data Annotation

I use EF Data Annotations in an ASP.NET MVC project and for the mandatory fields I define the fields as shown below:我在 ASP.NET MVC 项目中使用 EF 数据注释,对于必填字段,我定义了如下所示的字段:

Model:模型:

[Required(ErrorMessage = "Required!");
public string PhoneHome{ get; set; }

[Required(ErrorMessage = "Required!");
public string PhoneWork{ get; set; }

[Required(ErrorMessage = "Required!");
public string PhoneMobile { get; set; }


View:看法:

@Html.TextBoxFor(m => m.PhoneHome)
@Html.ValidationMessageFor(m => m.PhoneHome, null, new { @class = "field-validation-error" })

@Html.TextBoxFor(m => m.PhoneWork)
@Html.ValidationMessageFor(m => m.PhoneWork, null, new { @class = "field-validation-error" })

@Html.TextBoxFor(m => m.PhoneMobile )
@Html.ValidationMessageFor(m => m.PhoneMobile , null, new { @class = "field-validation-error" })


I want to make only one of these fields mandatory (if the user fill one of these fields it is ok, but if he does not fill any of them I want to display an error message and do not let he to submit form), but have no idea about the most suitable and smarter approach to perform this?我只想让这些字段中的一个是强制性的(如果用户填写其中一个字段是可以的,但是如果他不填写其中任何一个我想显示一条错误消息并且不要让他提交表单),但是不知道执行此操作的最合适和更智能的方法? Should I check all of these fields using JavaScript on submit and display necessary error message?我是否应该在提交时使用 JavaScript 检查所有这些字段并显示必要的错误消息? Or should I perform this by using the Data Annotations only?还是应该仅使用数据注释来执行此操作?

Okay so I made an example.好的,所以我举了一个例子。 I create a custom validation attribute that has some parameters like what properties are required and how many (minimum and maximum).我创建了一个自定义验证属性,其中包含一些参数,例如需要哪些属性以及数量(最小值和最大值)。 The naming is not the best but it does the job (not tested).命名不是最好的,但它可以完成工作(未经测试)。 You can remove the ICientValidatable if you do not care about valdiation on the client (using jquery validation, unobstrusive ...).如果您不关心客户端上的验证(使用 jquery 验证,不引人注目……),您可以删除 ICientValidatable。

The attribute is made like this:该属性是这样制作的:

public class OptionalRequired : ValidationAttribute, IClientValidatable
{
    /// <summary>
    /// The name of the client validation rule
    /// </summary>
    private readonly string type = "optionalrequired";

    /// <summary>
    /// The (minimum) amount of properties that are required to be filled in. Use -1 when there is no minimum. Default 1.
    /// </summary>
    public int MinimumAmount { get; set; } = 1;
    /// <summary>
    /// The maximum amount of properties that need to be filled in. Use -1 when there is no maximum. Default -1.
    /// </summary>
    public int MaximumAmount { get; set; } = -1;

    /// <summary>
    /// The collection of property names
    /// </summary>
    public string[] Properties { get; set; }


    public OptionalRequired(string[] properties)
    {
        Properties = properties;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        int validPropertyValues = 0;

        // Iterate the properties in the collection
        foreach (var propertyName in Properties)
        {
            // Find the property
            var property = validationContext.ObjectType.GetProperty(propertyName);

            // When the property is not found throw an exception
            if (property == null)
                throw new ArgumentException($"Property {propertyName} not found.");

            // Get the value of the property
            var propertyValue = property.GetValue(validationContext.ObjectInstance);

            // When the value is not null and not empty (very simple validation)
            if (propertyValue != null && String.IsNullOrEmpty(propertyValue.ToString()))
                validPropertyValues++;
        }

        // Check if the minimum allowed is exceeded
        if (MinimumAmount != -1 && validPropertyValues < MinimumAmount)
            return new ValidationResult($"You are required to fill in a minimum of {MinimumAmount} fields.");

        // Check if the maximum allowed is exceeded
        else if (MaximumAmount != -1 && validPropertyValues > MaximumAmount)
            return new ValidationResult($"You can only fill in {MaximumAmount} of fields");

        // 
        else
            return ValidationResult.Success;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ModelClientValidationRule rule = new ModelClientValidationRule();

        rule.ErrorMessage = "Enter your error message here or manipulate it on the client side";
        rule.ValidationParameters.Add("minimum", MinimumAmount);
        rule.ValidationParameters.Add("maximum", MaximumAmount);
        rule.ValidationParameters.Add("properties", string.Join(",", Properties));

        rule.ValidationType = type;

        yield return rule;
    }
}

And you use it like this on your class/viewmodel:你在你的类/视图模型上像这样使用它:

public class Person
{
    [OptionalRequired(new string[] { nameof(MobileNumber), nameof(LandLineNumber), nameof(FaxNumber) }, MinimumAmount = 2)]
    public string MobileNumber { get; set; }
    public string LandLineNumber { get; set; }
    public string FaxNumber { get; set; }
}

Using this configuration you would need to fill in at least 2 of the required fields otherwise an error will be shown.使用此配置,您需要填写至少 2 个必填字段,否则将显示错误。 You could put the attribute on every property so that the error message pops up on all of them.您可以将属性放在每个属性上,以便在所有属性上弹出错误消息。 It is what you want这是你想要的

For client validation I added the interface on the attribute and setup the different parameters but the JavaScript itself I do not have.对于客户端验证,我在属性上添加了接口并设置了不同的参数,但我没有 JavaScript 本身。 You would need to look it up (example here )你需要查一下( 这里的例子)

This code is not tested but I think it can give you a good idea of how things are done.这段代码没有经过测试,但我认为它可以让你很好地了解事情是如何完成的。

public class MyModel : IValidatableObject
{
    [Required(ErrorMessage = "Required!");
    public string PhoneHome{ get; set; }

    [Required(ErrorMessage = "Required!");
    public string PhoneWork{ get; set; }

    [Required(ErrorMessage = "Required!");
    public string PhoneMobile { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {

        if ((PhoneHome+PhoneWork+PhoneMobile).Length < 1)
        {
            yield return new ValidationResult("You should set up any phone number!", new [] { "ConfirmForm" });
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ASP.NET MVC 5-如何在ViewModel中添加[必需]数据注释 - ASP.NET MVC 5 - How to Add [Required] Data Annotation in ViewModel 如何使用 asp.net core 3.1/5 mvc 在 razor 视图中使用 * (基于 [Required] 注释)自动标记必填字段标签? - How can I automatically mark required field labels with a * (based on [Required] annotation) in a razor view using asp.net core 3.1/5 mvc? 在 MVC 之外使用 ASP.Net MVC 数据注释 - Using ASP.Net MVC Data Annotation outside of MVC ASP.NET MVC 向扩展的 IdentityRole 添加必需的注释 - ASP.NET MVC Adding Required Annotation to extended IdentityRole C#asp.net数据注释设置字段仅包含数字,但不是必需的 - C# asp.net data annotation setting field to only number but not required ASP.NET MVC 验证错误:<field> 字段为必填项 - ASP.NET MVC Validation error: The <field> field is required ASP.NET MVC中的ValidationResult:如何检测是否需要该字段 - ValidationResult in ASP.NET MVC: how to detect whether the field is required 如何解决 ASP.NET MVC 中的“需要名称字段”? - How to solve "Name field is required" in ASP.NET MVC? 如何使用ASP.Net MVC动态设置字段? - How Can I Set a Field as Required Dynamically Using ASP.Net MVC? 如何在ASP.NET MVC中忽略数据注释验证 - How to ignore data annotation validation in asp.net MVC
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM