How C# nullable reference types affects your ASP.NET Core routing

, 2 minutes to read

I thought that the new C# 8.0 fea­ture – non-nul­lable ref­er­ence types is just an In­tel­liSense fea­ture pow­ered by Roslyn that pre­vents null ref­er­ence ex­cep­tions. I was wrong. It may af­fect how your ap­pli­ca­tion works in many ways. More specif­i­cally, ev­ery­thing that use re­flection can start be­having dif­fer­ently. It in­cludes also ASP.NET Core rout­ing. Some bind­ings can stop work­ing when no ad­di­tional code changes are ap­plied.

Let us see it on ex­am­ple. Dif­fer­en­ti­a­tion be­tween nul­lable and non-nul­lable ref­er­ence types can be turned on in .csproj file:

<PropertyGroup> <Nullable>enable</Nullable> </PropertyGroup>

Do not think it does not ap­ply ei­ther on the an­no­ta­tions 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; } ... }

My­Value does not have Re­quired at­tribute so even if the JSON re­quest does not have my­Value prop­erty, bind­ing be­tween HTTP re­quest and MyMethod will work. That is true un­less you en­able nul­lable ref­er­ence types. Once you do that, you must de­clare that My­Value can be null be­cause it is the de­fault value when the prop­erty is not in­cluded in the re­quest. When the type is not nul­lable, the de­fault value can­not be ap­plied, and the prop­erty is re­quired au­to­mat­i­cally by syn­tax. Re­quired at­tribute in this case would be re­dun­dant. It be­came re­dun­dant also in con­tract pa­ram­e­ter dec­la­ra­tion.

public class MyContract { public string? MyValue { get; set; } ... }

My­Con­tract above has My­Value type of string? which means that the prop­erty is op­tional. The con­tract will con­tinue to work like be­fore when nul­lable ref­er­ence types were en­abled.