本文介绍了C# 无法在自定义验证属性中找到其他属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Trying to make my own Validation Attribute that uses a property name to find another property.

目前,我在查找其他属性时遇到问题.我似乎无法找到此属性(或实际上找不到任何属性).

Currently, I am having problems finding the other property. It seems I am unable to find this property (or in fact any properties).

property == null 的检查总是为真.

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

Any ideas why I wouldn't be able to find properties?

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

This is the custom filter I have made

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

    }

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

This is the model I am using behind my razor view.

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

我很感激自定义验证属性目前并没有真正做任何事情,但那是因为我一直被这个问题困住了.

I appreciate the fact that the custom validation attribute doesn't really do anything at the moment but that is becuase I have become stuck on this issue.

感谢您的帮助.

推荐答案

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

Let's use the following code snippet to help explain what is going on here:

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

    ...
}

在这个例子中,你可能希望 typeFullNameXXX.OrganisationDetailsModel,但 它不是:它实际上是 System.String(您要验证的属性 的类型).System.String 显然没有名为 e.g. 的属性.CompanyHouseToggleGetProperty 正确返回 null.

In this example, you might expect typeFullName to be XXX.OrganisationDetailsModel, but it isn't: it's actually System.String (the type of the property you’re trying to validate). System.String clearly does not have a property named e.g. CompanyHouseToggle and so GetProperty rightly returns null.

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

I've not seen many cases where [BindProperty] has been used more than once on a PageModel. It's certainly possible, but it appears that each property is treated as being individual and that the PageModel itself is not being validated.

为了解决这个问题,您可以将单独的属性转换为复杂类型并使用它.文档和示例在 PageModel 类内部为此使用了一个内联类.以下是更新后的 OrganisationDetailsModel 类的示例:

In order to work around this, you can just turn your individual properties into a complex type and use that instead. The docs and examples use an inline class for this, inside of the PageModel class. Here's an example of an updated OrganisationDetailsModel class:

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 的所有其他属性.
  • 添加类型为 InputModelInput 属性,使用 [BindProperty] 绑定.
  • 从现在已移动的原始属性中删除了 [BindProperty].
  • Creation of an InputModel class to hold all properties.
  • Removal of all other properties that have now moved into InputModel.
  • Addition of an Input property of type InputModel, that gets bound using [BindProperty].
  • Removed [BindProperty] from the original properties that have now been moved.

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

The last step is to replace any usage of e.g. CompanyNumber with Input.CompanyNumber in the PageModel's corresponding .cshtml and to ensure you use the Input. prefix when accessing properties within the PageModel class itself.

这篇关于C# 无法在自定义验证属性中找到其他属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 19:49