dotnet / dotnet/aspnetcore

PageModel ValidationContext ObjectInstance missing property values

Open
#41,582 7 comments 0 reactions 0 assignees View on GitHub
area-mvc bug
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

With the fix related to https://github.com/dotnet/aspnetcore/issues/4895 it is possible to use the `CompareAttribute` on a PageModel. A `ValidationAttribute` that isn't a `RequiredAttribute` only kicks in if the property value isn't null. In other words, the `CompareAttribute` only works if both properties have a value.

In my case I want to check if the other property has a certain value (true/false/etc.). If so, the actual property is required. See the code example below.

```csharp
public class RequiredIfTrueAttribute : RequiredAttribute
{
public RequiredIfTrueAttribute(string otherProperty)
{
ArgumentNullException.ThrowIfNull(otherProperty);

OtherProperty = otherProperty;
}

public string OtherProperty { get; private set; }

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var otherPropertyInfo = validationContext.ObjectType.GetProperty(OtherProperty);
if (otherPropertyInfo == null)
{
throw new MissingMemberException($"Property '{OtherProperty}' doesn't exist.");
}

object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
if (!Equals(true, otherPropertyValue))
{
return null;
}

return base.IsValid(value, validationContext);
}
}
```

The `otherPropertyValue` is always null. The `ObjectInstance` is the PageModel. All the properties of the model are null or default in the `ObjectInstance`.

The custom attribute is used in a PageModel like this:

```csharp
[BindProperties]
public class CreateModel : PageModel
{
[RequiredIfTrue(nameof(RequireDescription), ErrorMessage = "{0} is required.")]
public string Description { get; set; }

public bool RequireDescription { get; set; }

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

return Page();
}
}
```

### Expected Behavior

Model validation comes after model binding. The `ValidationContext` `ObjectInstance` must contain the model with the binded properties and have property values.

### Steps To Reproduce

_No response_

### Exceptions (if any)

_No response_

### .NET Version

net6.0

### Anything else?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.