【问题标题】:C# Unable to find other properties in custom validation attributeC#无法在自定义验证属性中找到其他属性
【发布时间】:2019-03-02 06:24:25
【问题描述】:

尝试制作我自己的验证属性,该属性使用属性名称来查找另一个属性。

目前,我在寻找其他房产时遇到问题。看来我找不到这个属性(或者实际上任何属性)。

property == null 的检查总是正确的。

任何想法为什么我无法找到属性?

这是我制作的自定义过滤器

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectInstance.GetType().GetProperty(PropertyName);

        if (property == null)
        {
            return new ValidationResult(string.Format(
                "Unknown property {0}",
                new[] { PropertyName }
            ));
        }

        var propertyValue = property.GetValue(validationContext.ObjectInstance);

        // Just for testing purposes.
        return new ValidationResult(ErrorMessage);

    }

这是我在剃刀视图后面使用的模型。

public class OrganisationDetailsModel : PageModel
{

    private readonly FormStateContext _context;

    public OrganisationDetailsModel(FormStateContext context)
    {
        _context = context;
    }

    [BindProperty]
    [RegularExpression(pattern: "(yes|no)")]
    [Required(ErrorMessage = "Please select if you are registered on companies house")]
    public string CompanyHouseToggle { get; set; }

    [BindProperty]
    [StringLength(60, MinimumLength = 3)]
    [RequiredIf("CompanyHouseToggle")]
    public string CompanyNumber { get; set; }

    [BindProperty]
    [StringLength(60, MinimumLength = 3)]
    [Required(ErrorMessage = "Enter your organisation name")]
    public string OrganisationName { get; set; }

    [BindProperty]
    [RegularExpression(pattern: "(GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})", ErrorMessage = "This VAT number is not recognised")]
    [Required(ErrorMessage = "Enter your vat number")]
    public string VatNumber { get; set; }

    public void OnGet()
    {
    }

    public IActionResult OnPost()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }
        return RedirectToPage("ApplicantDetails");
    }

我很欣赏自定义验证属性目前并没有真正做任何事情的事实,但那是因为我已经陷入了这个问题。

感谢您的帮助。

【问题讨论】:

    标签: c# asp.net razor asp.net-core .net-core


    【解决方案1】:

    由医生。 getProperties() 只返回publics。

    https://docs.microsoft.com/en-us/dotnet/api/system.type.getproperties?view=netframework-4.7.2

    所以如果想获得非公共财产。在下面找到。

    Get protected property value of base class using reflections


    protected override ValidationResult IsValid(object value, ValidationContext context) {
        var property = context.ObjectType.getProperty(context.MemberName);
    
        // TODO
    
        return ValidationResult.Success;
    }
    

    【讨论】:

    • 但是我想要获取的字段是publics?例如,CompanyHouseToggle 是我要检索的一个,它是公开的。
    • 好的。我找到了解决方案。 validationContext 中的 GetType() 方法来自 Object 类。所以,你错了。您应该使用成员“ObjectType”而不是 GetType()。
    【解决方案2】:

    让我们使用下面的代码 sn-p 来帮助解释这里发生了什么:

    protected override ValidationResult IsValid(object value, ValidationContext ctx)
    {
        var typeFullName = ctx.ObjectInstance.GetType().FullName;
    
        ...
    }
    

    在本例中,您可能认为typeFullNameXXX.OrganisationDetailsModel,但不是:它实际上是System.String属性的类型您正在尝试验证)。 System.String 显然没有名为 e.g. 的属性。 CompanyHouseToggleGetProperty 正确返回 null

    PageModel 上多次使用[BindProperty] 的情况并不多见。这当然是可能的,但似乎每个属性都被视为单独的,PageModel 本身没有经过验证。

    为了解决此问题,您只需将各个属性转换为复杂类型并使用它即可。文档和示例为此使用了一个内联类,在 PageModel 类中。这是一个更新的OrganisationDetailsModel 类的示例:

    public class OrganisationDetailsModel : PageModel
    {
        ...
    
        [BindProperty]
        public InputModel Input { get; set; }
    
        public void OnGet() { }
    
        public IActionResult OnPost()
        {
            if (!ModelState.IsValid)
                return Page();
    
            return RedirectToPage("ApplicantDetails");
        }
    
        public class InputModel
        {
            [RegularExpression(pattern: "(yes|no)")]
            [Required(ErrorMessage = "Please select if you are registered on companies house")]
            public string CompanyHouseToggle { get; set; }
    
            [StringLength(60, MinimumLength = 3)]
            [RequiredIf("CompanyHouseToggle")]
            public string CompanyNumber { get; set; }
    
            ...
        }
    }
    

    这包括以下更改:

    • 创建一个InputModel 类来保存所有属性。
    • 删除现在已移至 InputModel 的所有其他属性。
    • 添加InputModel 类型的Input 属性,使用[BindProperty] 绑定。
    • 从现在已移动的原始属性中删除了[BindProperty]

    最后一步是替换任何用法,例如CompanyNumberInput.CompanyNumberPageModel 对应的 .cshtml 中,并确保在访问 PageModel 类本身的属性时使用 Input. 前缀。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-28
      • 1970-01-01
      • 1970-01-01
      • 2019-12-17
      • 2011-09-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多