C#无法在自定义验证属性中找到其他属性

时间:2018-09-26 12:58:46

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

尝试创建自己的验证属性,该属性使用属性名称查找另一个属性。

目前,我在寻找其他财产方面遇到问题。看来我找不到此属性(或实际上任何属性)。

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");
    }

我很欣赏以下事实:自定义验证属性目前并没有真正做任何事情,但这是因为我一直陷在这个问题上。

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

通过文档。 getProperties()仅返回公众。

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;
}

答案 1 :(得分:0)

让我们使用以下代码段来帮助解释这里发生的事情:

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

    ...
}

在此示例中,您可能期望typeFullNameXXX.OrganisationDetailsModel,但并非:实际上是System.String您要验证的属性。 System.String显然没有名为的属性。 CompanyHouseToggle,因此GetProperty正确地返回了null

我还没有看到在[BindProperty]上多次使用PageModel的情况。当然可以,但是似乎每个属性都被视为单个属性,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的所有其他属性。
  • 添加类型为Input的{​​{1}}属性,该属性使用InputModel进行绑定。
  • 从现在已移动的原始属性中删除了[BindProperty]

最后一步是替换任何用法,例如{{1}中对应的[BindProperty]中的CompanyNumberInput.CompanyNumber,并确保在访问PageModel类本身内的属性时使用.cshtml前缀