Azure 应用服务似乎在 .NET 5 模式下启用了 NLS

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

在花了无数个小时来深入了解错误的核心之后,我最终将问题归结为在 .NET 5 中使用 string.CompareStringComparison.InvariantCultureIgnoreCase

考虑以下两个 dotnetfiddle:

当 运行 .NET 4.7.2 时,结果为 -1,当 运行 .NET 5 时,结果为 1。

经过一些浏览,这导致了以下通知:

因此,通过这种方式,-1 的结果是 NLS 版本,而 1 的 .NET 5 结果是 ICU 版本。

但是,当我在 .NET 5 模式下启动 Azure 应用服务时,上述代码在 Razor 页面中的结果是 -1,又名:NLS 版本。

这可能会导致各种奇怪的问题,因为两个不同的系统会导致意外的结果。

当我将以下内容添加到我的项目文件中时,如上一篇文章所述,我的本地环境也输出-1。

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

无论我在 Azure 中使用什么样的配置,它都会一直输出 -1。

长话短说,Azure 上发生了一些事情。根据文档,我的 Windows 版本足够新,可以启用 ICU。看起来 Azure 应用服务正在使用强制 NLS 模式,或者是 运行 我的本地计算机没有的某个 ICU 版本。

任何人都知道我如何确定 Azure 使用的是哪个 ICU 版本(如果有的话),以便我可以使用文档中的建议来使用 AppLocalIcu?否则,如果某些事情明显在 Azure 一边,那么我的问题是报告此事件的最佳位置是什么?

我认为你可以使用 this method 在 Azure 应用服务中启用 App-local ICU。

如果您的 Web 应用程序是依赖于框架的应用程序,您可以通过 NuGet 包使用 ICU。

  • 在您的 web 应用程序 项目中安装 NuGet 包 Microsoft.ICU.ICU4C.Runtime
  • 编辑项目文件以在 <ItemGroup> 部分添加 <RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="<suffix>:<version> or <version>" />。或者您可以添加值为 <suffix>:<version><version>.
  • 的应用程序设置 DOTNET_SYSTEM_GLOBALIZATION_APPLOCALICU

那你就可以随意使用Azure App Service中的特殊版ICU了

Azure 应用服务团队的某个人对此进行了深入研究:

  • 大多数 Azure 应用服务 运行 Windows 2016 年,更具体地说是在撰写本文时:
Major  Minor  Build  Revision
-----  -----  -----  --------
10     0      14393  0   
  • 在 Windows 服务器环境中,Windows Server 2019 中引入了 ICU。

所以回答我自己的问题:Azure 应用服务确实默认使用 NLS。这不是错误!

通过在项目文件中包含以下内容,将强制执行 ICU:

<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>

符合@Crazy Crab提到的方案,谢谢!

另请参阅 https://www.nuget.org/packages/Microsoft.ICU.ICU4C.Runtime 了解最新版本(撰写本文时为 68.2.0.9)。

我将接受我自己的回答,因为我觉得它可以更好地回答“为什么会这样”的问题,而不仅仅是修复它。