简体   繁体   English

如何使用由 model 属性组成的参数创建自定义验证属性

[英]How to create a custom validation attribute with parameters consisting of model properties

I am currently trying to make a site on asp.net core.我目前正在尝试在 asp.net 内核上创建一个站点。 When i press the submit button, i want all the validation messages to come up if there is incorrect input.当我按下提交按钮时,如果输入不正确,我希望所有验证消息都出现。

在此处输入图像描述

For now, i have the name and the phone number validation messages working using 'asp-validation-for=Client.Name' and Client.ContactNumber.现在,我有使用“asp-validation-for=Client.Name”和Client.ContactNumber 的姓名和电话号码验证消息。 Now i want to be able to validate from the server side if the user has checked at least one of the boxes off, or filled in the 'Other' field.现在我希望能够从服务器端验证用户是否至少选中了一个框,或者填写了“其他”字段。 So i tried to see if i can make a custom attribute which would validate it but havent gotten any luck.所以我试图看看我是否可以制作一个自定义属性来验证它但没有得到任何运气。 I have tried sending in the properties of the Client class but it throws an error saying "An object reference is required for the non-static field, method, or property 'Client.'".我已尝试发送客户端 class 的属性,但它会引发错误,提示“非静态字段、方法或属性‘客户端’需要 object 引用。”。 I have also tried the top solution here CS0120: An object reference is required for the nonstatic field, method, or property 'foo' , but I think in my case those solutions are not possible.我也尝试过CS0120 的最佳解决方案:非静态字段、方法或属性 'foo' 需要一个 object 引用,但我认为在我的情况下这些解决方案是不可能的。

My code for the files that i am working with are below我正在使用的文件的代码如下

Code for Client.cs (model class) Client.cs 的代码(模型类)

public class Client
{
    //some attributes

    [Required]
    public string Name { get; set; }

    [Required]
    [DisplayName("Bookkeeping")]
    public bool Bookkeeping { get; set; }

    [Required]
    [DisplayName("Personal Income Taxation")]
    public bool Personal_Income_Taxation { get; set; }

    [Required]
    [DisplayName("Self-Employed Business Taxes")]
    public bool Self_Employed_Business_Taxes { get; set; }

    [Required]
    [DisplayName("GST/PST/WCB Returns")]
    public bool GST_PST_WCB_Returns { get; set; }

    [Required]
    [DisplayName("Tax Returns")]
    public bool Tax_Returns { get; set; }

    [Required]
    [DisplayName("Payroll Services")]
    public bool Payroll_Services { get; set; }

    [Required]
    [DisplayName("Previous Year Filings")]
    public bool Previous_Year_Filings { get; set; }

    [Required]
    [DisplayName("Govt. Requisite Form Applicaitons")]
    public bool Government_Requisite_Form_Applications { get; set; }

    public string Other { get; set; }

    [CheckboxAndOtherValidation(bookkeeping: Bookkeeping,
        personal_Income_Taxation: Personal_Income_Taxation,
        self_Employed_Business_Taxes: Self_Employed_Business_Taxes,
        gST_PST_WCB_Returns: GST_PST_WCB_Returns,
        tax_Returns: Tax_Returns,
        payroll_Services: Payroll_Services,
        previous_Year_Filings: Previous_Year_Filings,
        government_Requisite_Form_Applications: Government_Requisite_Form_Applications,
        other: Other)]
    public bool AreCheckboxesAndOtherValid { get; set; }

FreeConsultation.cshtml (view page) FreeConsultation.cshtml(查看页面)

 <div class="container" style="padding:30px;"> <br /> <h1 class="text-info">Create New Client</h1><br /> <form method="post"> <div class="text-danger" asp-validation-summary="ModelOnly"></div> <div class="form-group row"> <div class="col-3"> <label asp-for="Client.Name"></label> </div> <div class="col-6"> <input type="text" asp-for="Client.Name" class="form-control" /> </div> <span class="text-danger col-3" asp-validation-for="Client.Name"></span> </div> <!-- More code -->

My utility class i created for custom validation attribute - CheckboxAndOtherValidation.cs我为自定义验证属性创建的实用程序 class - CheckboxAndOtherValidation.cs

    public class CheckboxAndOtherValidation : ValidationAttribute
{
    private readonly bool Bookkeeping;
    private readonly bool Personal_Income_Taxation;
    private readonly bool Self_Employed_Business_Taxes;
    private readonly bool GST_PST_WCB_Returns;
    private readonly bool Tax_Returns;
    private readonly bool Payroll_Services;
    private readonly bool Previous_Year_Filings;
    private readonly bool Government_Requisite_Form_Applications;
    private readonly string Other;

    public CheckboxAndOtherValidation(bool bookkeeping,
        bool personal_Income_Taxation,
        bool self_Employed_Business_Taxes,
        bool gST_PST_WCB_Returns,
        bool tax_Returns,
        bool payroll_Services,
        bool previous_Year_Filings,
        bool government_Requisite_Form_Applications,
        string other)
    {
        this.Bookkeeping = bookkeeping;
        this.Personal_Income_Taxation = personal_Income_Taxation;
        this.Self_Employed_Business_Taxes = self_Employed_Business_Taxes;
        this.GST_PST_WCB_Returns= gST_PST_WCB_Returns;
        this.Tax_Returns = tax_Returns;
        this.Payroll_Services = payroll_Services;
        this.Previous_Year_Filings = previous_Year_Filings;
        this.Government_Requisite_Form_Applications = government_Requisite_Form_Applications;
        this.Other = other;

    }

    public override bool IsValid(object value)
    {
        return base.IsValid(value);
    }
}

Is there any other way to tackle this?有没有其他方法可以解决这个问题? (Preferably with custom attribute). (最好使用自定义属性)。 First time posting a question so pardon me if there is anything missing.第一次发问题,如有遗漏请见谅。 Thanks谢谢

EDIT编辑

I was able to make the checkbox error come from the server side with the help of a solution, but i still have the issue that when i press the submit button, the checkbox error doesn't come at the same time as the other two.在解决方案的帮助下,我能够使复选框错误来自服务器端,但我仍然有一个问题,即当我按下提交按钮时,复选框错误不会与其他两个同时出现。 By following a tutorial, i was able to show the other two errors from the client side by including this piece of code in my view which comes with the creation of an asp.net core project通过遵循教程,我能够通过在我的视图中包含这段代码来从客户端显示其他两个错误,该代码伴随着 asp.net 核心项目的创建

 @section Scripts { <partial name="_ValidationScriptsPartial" /> }

_ValidationScriptsPartial.cshtml _ValidationScriptsPartial.cshtml

 <environment include="Development"> <script src="~/Identity/lib/jquery-validation/dist/jquery.validate.js"></script> <script src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script> </environment> <environment exclude="Development"> <script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js" asp-fallback-src="~/Identity/lib/jquery-validation/dist/jquery.validate.min.js" asp-fallback-test="window.jQuery && window.jQuery.validator" crossorigin="anonymous" integrity="SOME INFO"> </script> <script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.9/jquery.validate.unobtrusive.min.js" asp-fallback-src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive" crossorigin="anonymous" integrity="SOME INFO"> </script> </environment>

Some references are here一些参考是here

  1. Article custom-data-annotation-validation-in-mvc文章custom-data-annotation-validation-in-mvc
  2. Source code of CompareAttribute.cs and ComparePropertyAttribute.cs CompareAttribute.csComparePropertyAttribute.cs的源代码
  3. 3rd-party ExpressiveAnnotations 3rd-party ExpressiveAnnotations

So in a similar way, a custom ValidationAttribute can use reflection to get runtime value by its property name ( the name from declaration or argument ) to see if the property have the required value or format you need.因此,以类似的方式,自定义ValidationAttribute可以使用反射通过其属性名称( the name from declaration or argument )来获取运行时值,以查看该属性是否具有所需的值或格式。

public class CheckboxAndOtherValidation : ValidationAttribute
{
    readonly object TRUE = true;
    string[] _alltheOtherProperty;

    public CheckboxAndOtherValidation(params string[] alltheOthersProperty)
    {
        _alltheOtherProperty = alltheOthersProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (_alltheOtherProperty?.Count() > 0 != true)
        {
            return ValidationResult.Success;
        }

        var otherPropertyInfo = validationContext.ObjectType.GetProperty(nameof(Client.Other));
        if (otherPropertyInfo != null)
        {
            object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
            if (otherPropertyValue != null && !string.IsNullOrEmpty(otherPropertyValue.ToString()))
            {
                return ValidationResult.Success;
            }
        }

        for (var i = 0; i < _alltheOtherProperty.Length; ++i)
        {
            var prop = _alltheOtherProperty[i];
            var propertyInfo = validationContext.ObjectType.GetProperty(prop);
            if (propertyInfo == null)
            {
                continue;
            }

            object propertyValue = propertyInfo.GetValue(validationContext.ObjectInstance, null);
            if (Equals(TRUE, propertyValue))
            {
                return ValidationResult.Success;
            }
        }

        return new ValidationResult("Must exist at least one field is true", _alltheOtherProperty);
    }
}

Cus I choose passing property name array list as argument, now class Client could have a simplified and clearer usage like this,因为我选择传递属性名称数组列表作为参数,现在 class客户端可以有这样一个简化和更清晰的用法,

public class Client
{
    [CheckboxAndOtherValidation(nameof(Bookkeeping),
        nameof(Personal_Income_Taxation),
        nameof(Self_Employed_Business_Taxes),
        nameof(GST_PST_WCB_Returns),
        nameof(Tax_Returns),
        nameof(Payroll_Services),
        nameof(Previous_Year_Filings),
        nameof(Government_Requisite_Form_Applications))]
    public bool AreCheckboxesAndOtherValid { get; set; }
}    

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM