Search code examples
c#azureglobalizationicunls

Azure App Service seems to have NLS enabled in .NET 5 mode


After spending countless of hours on getting to the core of a bug, I eventually boiled down a problem to the use of string.Compare with StringComparison.InvariantCultureIgnoreCase in .NET 5.

Consider the following two dotnetfiddles:

When running the .NET 4.7.2 you get -1 as a result, when running .NET 5 you get 1 as a result.

After some browsing, this led to the following notice:

So, going by this, a result of -1 is the NLS version, whereas the .NET 5 result of 1 is the ICU version.

However, when I spin up an Azure App Service in .NET 5 mode, the result of the above code in a Razor page is -1, AKA: the NLS version.

This can cause all kinds of weird issues, because two different systems lead to unexpected results.

When I add add the following to my project-file, as mentioned in the last article, my local environment also outputs a -1.

<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" />
</ItemGroup>

No matter what kind of configuration I use in Azure, it will always keep outputting -1.

Long story, something is up on Azure. As per documentation, my Windows version is new enough to have ICU enabled. Looks like the Azure App Service is either using a forced NLS mode, or is running some ICU version my local machine doesn't have.

Anyone know how I can figure out which ICU version (if any) Azure is using, so I can use the suggestion from the documentation to use a AppLocalIcu? Otherwise, if something is clearly on the side of Azure, then my question is what the best location would be to report this?


Solution

  • Someone at the Azure App Service team dove into this:

    • Most Azure App Services run on Windows 2016, more specifically at the time of writing:
    Major  Minor  Build  Revision
    -----  -----  -----  --------
    10     0      14393  0   
    
    • In the Windows Server landscape ICU was introduced in Windows Server 2019.

    So to answer my own question: Azure App Services are indeed using NLS by default. This is not a bug!

    By including the following in your project-file, ICU will be forced:

    <ItemGroup Condition="'$(OS)' == 'Windows_NT'">
      <PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.9" />
      <RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="68.2" />
    </ItemGroup>
    

    This is in line with the solution that @Crazy Crab mentioned, thanks!

    Also see https://www.nuget.org/packages/Microsoft.ICU.ICU4C.Runtime for the latest version (68.2.0.9 at the time of writing).

    I'm going to accept my own answer, as I feel it gives a better answer to the "Why is this happening" question, rather than just fixing it.