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).
The check for property == null
is always coming up as true.
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.
Thanks for any help.
Let's use the following code snippet to help explain what is going on here:
In this example, you might expect
typeFullName
to beXXX.OrganisationDetailsModel
, but it isn't: it's actuallySystem.String
(the type of the property you’re trying to validate).System.String
clearly does not have a property named e.g.CompanyHouseToggle
and soGetProperty
rightly returnsnull
.I've not seen many cases where
[BindProperty]
has been used more than once on aPageModel
. It's certainly possible, but it appears that each property is treated as being individual and that thePageModel
itself is not being validated.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 updatedOrganisationDetailsModel
class:This includes the following changes:
InputModel
class to hold all properties.InputModel
.Input
property of typeInputModel
, that gets bound using[BindProperty]
.[BindProperty]
from the original properties that have now been moved.The last step is to replace any usage of e.g.
CompanyNumber
withInput.CompanyNumber
in thePageModel
's corresponding.cshtml
and to ensure you use theInput.
prefix when accessing properties within thePageModel
class itself.By the doc. getProperties() only return publics.
https://docs.microsoft.com/en-us/dotnet/api/system.type.getproperties?view=netframework-4.7.2
So if want to get non-public properties. Find on belows.
Get protected property value of base class using reflections