I thought that the new C# 8.0 feature – non-nullable reference types – was just an IntelliSense feature powered by Roslyn that prevents null reference exceptions. I was wrong. It may affect how your application works in many ways. More specifically, everything that uses reflection can start behaving differently. This includes ASP.NET Core routing. Some bindings can stop working when no additional code changes are applied.
Let us see it with an example. Differentiation between nullable and non-nullable reference types can be turned on in the .csproj
file:
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
Do not think it does not apply either to the annotations
value:
<PropertyGroup>
<Nullable>annotations</Nullable>
</PropertyGroup>
The route may look like this:
[HttpPost]
public async Task MyMethod([Required, FromBody] MyContract contract) {
...
}
public class MyContract {
public string MyValue { get; set; }
...
}
MyValue
does not have the Required
attribute, so even if the JSON request does not have the myValue
property, binding between the HTTP request and MyMethod
will work. That is true unless you enable nullable reference types. Once you do that, you must declare that MyValue
can be null because it is the default value when the property is not included in the request. When the type is not nullable, the default value cannot be applied, and the property is required automatically by the syntax. The Required
attribute in this case would be redundant. It also becomes redundant in the contract
parameter declaration.
public class MyContract {
public string? MyValue { get; set; }
...
}
MyContract
above has MyValue
of type string?
, which means that the property is optional. The contract will continue to work like before when nullable reference types were enabled.