diff --git a/.azure/pipelines/blazor-daily-tests.yml b/.azure/pipelines/blazor-daily-tests.yml new file mode 100644 index 000000000000..77ac645ff504 --- /dev/null +++ b/.azure/pipelines/blazor-daily-tests.yml @@ -0,0 +1,67 @@ +# Uses Scheduled Triggers, which aren't supported in YAML yet. +# https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=vsts&tabs=yaml#scheduled + +# Daily Tests for Blazor +# These use Sauce Labs resources, hence they run daily rather than per-commit. + +# We just need one Windows machine because all it does is trigger SauceLabs. +variables: + - ${{ if ne(variables['System.TeamProject'], 'public') }}: + - group: DotNet-MSRC-Storage + - group: AzureDevOps-Artifact-Feeds-Pats + - name: SAUCE_CONNECT_DOWNLOAD_ON_INSTALL + value: true + - name: E2ETESTS_SauceTest + value: true + - name: E2ETESTS_Sauce__TunnelIdentifier + value: 'blazor-e2e-sc-proxy-tunnel' + - name: E2ETESTS_Sauce__HostName + value: 'sauce.local' + +jobs: +- template: jobs/default-build.yml + parameters: + buildDirectory: src/Components + isTestingJob: true + agentOs: Windows + jobName: BlazorDailyTests + jobDisplayName: "Blazor Daily Tests" + afterBuild: + + # macOS/Safari + - script: 'dotnet test --no-build --configuration Release --filter "StandaloneAppTest"' + workingDirectory: 'src/Components/test/E2ETest' + displayName: 'Run Blazor tests - macOS/Safari' + condition: succeededOrFailed() + env: + # Secrets need to be explicitly mapped to env variables. + E2ETESTS_Sauce__Username: '$(asplab-sauce-labs-username)' + E2ETESTS_Sauce__AccessKey: '$(asplab-sauce-labs-access-key)' + # Set platform/browser configuration. + E2ETESTS_Sauce__TestName: 'Blazor Daily Tests - macOS/Safari' + E2ETESTS_Sauce__PlatformName: 'macOS 10.14' + E2ETESTS_Sauce__BrowserName: 'Safari' + # Need to explicitly set version here because some older versions don't support timeouts in Safari. + E2ETESTS_Sauce__SeleniumVersion: '3.4.0' + + # Android/Chrome + - script: 'dotnet test --no-build --configuration Release --filter "StandaloneAppTest"' + workingDirectory: 'src/Components/test/E2ETest' + displayName: 'Run Blazor tests - Android/Chrome' + condition: succeededOrFailed() + env: + # Secrets need to be explicitly mapped to env variables. + E2ETESTS_Sauce__Username: '$(asplab-sauce-labs-username)' + E2ETESTS_Sauce__AccessKey: '$(asplab-sauce-labs-access-key)' + # Set platform/browser configuration. + E2ETESTS_Sauce__TestName: 'Blazor Daily Tests - Android/Chrome' + E2ETESTS_Sauce__PlatformName: 'Android' + E2ETESTS_Sauce__PlatformVersion: '10.0' + E2ETESTS_Sauce__BrowserName: 'Chrome' + E2ETESTS_Sauce__DeviceName: 'Android GoogleAPI Emulator' + E2ETESTS_Sauce__DeviceOrientation: 'portrait' + E2ETESTS_Sauce__AppiumVersion: '1.9.1' + artifacts: + - name: Windows_Logs + path: artifacts/log/ + publishOnError: true \ No newline at end of file diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index d3d8637c4108..1dabcb870e7d 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -525,6 +525,40 @@ stages: parameters: inputName: Linux_musl_x64 + # Build Linux Musl ARM + - template: jobs/default-build.yml + parameters: + jobName: Linux_musl_arm_build + jobDisplayName: "Build: Linux Musl ARM" + agentOs: Linux + useHostedUbuntu: false + container: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-cross-arm-alpine-20200827125937-14441ae + buildScript: ./build.sh + buildArgs: + --arch arm + --os-name linux-musl + --pack + --all + --no-build-nodejs + --no-build-java + -p:OnlyPackPlatformSpecificPackages=true + -p:AssetManifestFileName=aspnetcore-Linux_musl_arm.xml + $(_BuildArgs) + $(_PublishArgs) + $(_InternalRuntimeDownloadArgs) + installNodeJs: false + installJdk: false + artifacts: + - name: Linux_musl_arm_Logs + path: artifacts/log/ + publishOnError: true + includeForks: true + - name: Linux_musl_arm_Packages + path: artifacts/packages/ + - template: jobs/codesign-xplat.yml + parameters: + inputName: Linux_musl_arm + # Build Linux Musl ARM64 - template: jobs/default-build.yml parameters: diff --git a/.editorconfig b/.editorconfig index b210dcdbf67f..bfb8b47a5063 100644 --- a/.editorconfig +++ b/.editorconfig @@ -42,3 +42,8 @@ end_of_line = lf [*.{razor,cshtml}] charset = utf-8-bom + +[*.cs] +dotnet_diagnostic.CA1304.severity = error +dotnet_diagnostic.CA1305.severity = error +dotnet_diagnostic.CA1310.severity = error diff --git a/.github/ISSUE_TEMPLATE/razor_tooling.md b/.github/ISSUE_TEMPLATE/razor_tooling.md index 1441431a6695..8b5971cc9e73 100644 --- a/.github/ISSUE_TEMPLATE/razor_tooling.md +++ b/.github/ISSUE_TEMPLATE/razor_tooling.md @@ -34,26 +34,13 @@ We will close this issue if: Please collect the data below before reporting your issue to aid us in diagnosing the root cause. -#### Activity log +#### Activity log (only needed if VS crashes) [Here](https://docs.microsoft.com/en-us/visualstudio/extensibility/how-to-use-the-activity-log?view=vs-2019#to-examine-the-activity-log) are the instructions on how to generate/acquire one. Note that GitHub does not generally allow .xml files to be uploaded with issues. -#### Razor Language Server Client log - -
-Razor Language Server Client Log Output - -Paste log output here - -
- -#### HTML Language Server Client log - -
-HTML Language Server Client Log Output - -Paste log output here - -
+#### Language Server logs +1. Run Visual Studio with the [/Log](https://docs.microsoft.com/en-us/visualstudio/ide/reference/log-devenv-exe?view=vs-2019) command line switch +2. Reproduce the issue +3. Provide the logs located at `%Temp%\VisualStudio\LSP` ### Further technical details - VS version (Help => About Microsoft Visual Studio, i.e. 16.8.0 Preview 1 30313.27...). If in Codespaces there will be two versions (server and client), please provide both. diff --git a/.github/workflows/runtime-sync.yml b/.github/workflows/runtime-sync.yml index 03e7e8f9d6ba..0b70c9551c96 100644 --- a/.github/workflows/runtime-sync.yml +++ b/.github/workflows/runtime-sync.yml @@ -21,14 +21,14 @@ jobs: # Test this script using changes in a fork repository: 'dotnet/aspnetcore' path: aspnetcore - ref: release/5.0 + ref: master - name: Checkout runtime uses: actions/checkout@v2.0.0 with: # Test this script using changes in a fork repository: 'dotnet/runtime' path: runtime - ref: release/5.0 + ref: master - name: Copy shell: cmd working-directory: .\runtime\src\libraries\Common\src\System\Net\Http\aspnetcore\ @@ -67,6 +67,6 @@ jobs: title: 'Sync shared code from runtime' body: 'This PR was automatically generated to sync shared code changes from runtime. Fixes #18943' labels: area-servers - base: release/5.0 + base: master branch: github-action/sync-runtime branch-suffix: timestamp diff --git a/AspNetCore.sln b/AspNetCore.sln index ceb029889f9e..1796f77d8dab 100644 --- a/AspNetCore.sln +++ b/AspNetCore.sln @@ -1503,7 +1503,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.App.Un EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Localization", "Localization", "{3D34C81F-2CB5-459E-87E9-0CC04757A2A0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalizationWasmApp", "src\Components\test\testassets\GlobalizationWasmApp\GlobalizationWasmApp.csproj", "{04CFE286-6D32-41EF-8887-4B5F8086A365}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GlobalizationWasmApp", "src\Components\test\testassets\GlobalizationWasmApp\GlobalizationWasmApp.csproj", "{04CFE286-6D32-41EF-8887-4B5F8086A365}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Localization.Abstractions", "src\Localization\Abstractions\src\Microsoft.Extensions.Localization.Abstractions.csproj", "{FEF97646-9BC9-4D1B-A939-784D915C18A4}" EndProject @@ -1519,6 +1519,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Loggin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.AzureAppServices.Tests", "src\Logging.AzureAppServices\test\Microsoft.Extensions.Logging.AzureAppServices.Tests.csproj", "{43E3B132-2486-44A3-92C6-39E39724FAFD}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{7B739F28-21DE-435D-9EA6-579064932350}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoutingWebSite", "src\Http\Routing\test\testassets\RoutingWebSite\RoutingWebSite.csproj", "{F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoutingSandbox", "src\Http\Routing\test\testassets\RoutingSandbox\RoutingSandbox.csproj", "{0EBEE047-CBAD-4A69-8095-E3961B863446}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "src\Http\Routing\test\testassets\Benchmarks\Benchmarks.csproj", "{B4F76DF0-1638-42DA-B46A-30DC16AECEAB}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SiteExtensions", "SiteExtensions", "{DFC4F588-B4B4-484B-AB93-B36721374AD3}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LoggingAggregate", "LoggingAggregate", "{48FF1D87-5066-4294-B802-2D1B478C6EB6}" @@ -1539,6 +1547,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{E83B0BCC-A8E EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostingStartup", "src\SiteExtensions\Sdk\HostingStartup\HostingStartup.csproj", "{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IgnitorSample", "src\Components\Samples\IgnitorSample\IgnitorSample.csproj", "{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Tests.Utils", "src\SignalR\common\testassets\Tests.Utils\Microsoft.AspNetCore.SignalR.Tests.Utils.csproj", "{C1CDD339-B51B-42BE-99F2-F39A4EC0D404}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{BB3D6EDD-AE71-4D25-B61B-7EBF7A1BA1D1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -7199,18 +7213,6 @@ Global {BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x64.Build.0 = Release|Any CPU {BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x86.ActiveCfg = Release|Any CPU {BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x86.Build.0 = Release|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.Build.0 = Debug|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.ActiveCfg = Debug|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.Build.0 = Debug|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.ActiveCfg = Debug|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.Build.0 = Debug|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.ActiveCfg = Release|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.Build.0 = Release|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.ActiveCfg = Release|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.Build.0 = Release|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.ActiveCfg = Release|Any CPU - {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.Build.0 = Release|Any CPU {010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -7223,6 +7225,18 @@ Global {010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x64.Build.0 = Release|Any CPU {010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x86.ActiveCfg = Release|Any CPU {010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x86.Build.0 = Release|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.ActiveCfg = Debug|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.Build.0 = Debug|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.ActiveCfg = Debug|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.Build.0 = Debug|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.Build.0 = Release|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.ActiveCfg = Release|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.Build.0 = Release|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.ActiveCfg = Release|Any CPU + {04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.Build.0 = Release|Any CPU {FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|Any CPU.Build.0 = Debug|Any CPU {FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -7295,6 +7309,42 @@ Global {43E3B132-2486-44A3-92C6-39E39724FAFD}.Release|x64.Build.0 = Release|Any CPU {43E3B132-2486-44A3-92C6-39E39724FAFD}.Release|x86.ActiveCfg = Release|Any CPU {43E3B132-2486-44A3-92C6-39E39724FAFD}.Release|x86.Build.0 = Release|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Debug|x64.ActiveCfg = Debug|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Debug|x64.Build.0 = Debug|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Debug|x86.ActiveCfg = Debug|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Debug|x86.Build.0 = Debug|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Release|Any CPU.Build.0 = Release|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Release|x64.ActiveCfg = Release|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Release|x64.Build.0 = Release|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Release|x86.ActiveCfg = Release|Any CPU + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C}.Release|x86.Build.0 = Release|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Debug|x64.ActiveCfg = Debug|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Debug|x64.Build.0 = Debug|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Debug|x86.ActiveCfg = Debug|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Debug|x86.Build.0 = Debug|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Release|Any CPU.Build.0 = Release|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Release|x64.ActiveCfg = Release|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Release|x64.Build.0 = Release|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Release|x86.ActiveCfg = Release|Any CPU + {0EBEE047-CBAD-4A69-8095-E3961B863446}.Release|x86.Build.0 = Release|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Debug|x64.ActiveCfg = Debug|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Debug|x64.Build.0 = Debug|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Debug|x86.ActiveCfg = Debug|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Debug|x86.Build.0 = Debug|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Release|Any CPU.Build.0 = Release|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Release|x64.ActiveCfg = Release|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Release|x64.Build.0 = Release|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Release|x86.ActiveCfg = Release|Any CPU + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB}.Release|x86.Build.0 = Release|Any CPU {563A3FFA-32DA-4ADA-891C-E00897BD919E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {563A3FFA-32DA-4ADA-891C-E00897BD919E}.Debug|Any CPU.Build.0 = Debug|Any CPU {563A3FFA-32DA-4ADA-891C-E00897BD919E}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -7367,6 +7417,30 @@ Global {5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x64.Build.0 = Release|Any CPU {5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x86.ActiveCfg = Release|Any CPU {5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x86.Build.0 = Release|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|x64.ActiveCfg = Debug|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|x64.Build.0 = Debug|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|x86.ActiveCfg = Debug|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|x86.Build.0 = Debug|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|Any CPU.Build.0 = Release|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|x64.ActiveCfg = Release|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|x64.Build.0 = Release|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|x86.ActiveCfg = Release|Any CPU + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|x86.Build.0 = Release|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Debug|x64.ActiveCfg = Debug|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Debug|x64.Build.0 = Debug|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Debug|x86.ActiveCfg = Debug|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Debug|x86.Build.0 = Debug|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Release|Any CPU.Build.0 = Release|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Release|x64.ActiveCfg = Release|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Release|x64.Build.0 = Release|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Release|x86.ActiveCfg = Release|Any CPU + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -8117,10 +8191,10 @@ Global {37329855-01B8-4B03-9765-1A941B06E43C} = {8C15FD04-7F90-43FC-B488-023432FE3CE1} {D3246226-BC1A-47F1-8E3E-C3380A8F13FB} = {8C15FD04-7F90-43FC-B488-023432FE3CE1} {B06ADD57-E855-4D8C-85DC-B323509AE540} = {898F7E0B-1671-42CB-9DFB-689AFF212ED3} - {04CFE286-6D32-41EF-8887-4B5F8086A365} = {6126DCE4-9692-4EE2-B240-C65743572995} {BAD47859-95DF-4C8F-9AF7-C48B68F478A1} = {A4C26078-B6D8-4FD8-87A6-7C15A3482038} {010A9638-F20E-4FE6-A186-85732BFC9CB0} = {A4C26078-B6D8-4FD8-87A6-7C15A3482038} {3D34C81F-2CB5-459E-87E9-0CC04757A2A0} = {017429CC-C5FB-48B4-9C46-034E29EE2F06} + {04CFE286-6D32-41EF-8887-4B5F8086A365} = {6126DCE4-9692-4EE2-B240-C65743572995} {FEF97646-9BC9-4D1B-A939-784D915C18A4} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0} {839CE175-E0D9-43B9-9FA8-F32C47E7F56B} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0} {50BF2926-7435-4F4B-88A9-3D0EDEB67FC8} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0} @@ -8128,6 +8202,10 @@ Global {3EAB9890-2C01-444C-ACA0-D77B29CDE08B} = {017429CC-C5FB-48B4-9C46-034E29EE2F06} {3E29454A-C4DC-44B7-AF0A-A782AD2E73BC} = {3EAB9890-2C01-444C-ACA0-D77B29CDE08B} {43E3B132-2486-44A3-92C6-39E39724FAFD} = {3EAB9890-2C01-444C-ACA0-D77B29CDE08B} + {7B739F28-21DE-435D-9EA6-579064932350} = {17DD5861-0635-46D0-84BA-6B163150AA4F} + {F502ED22-EB37-4EF8-BFA0-3EFB3E2BE20C} = {7B739F28-21DE-435D-9EA6-579064932350} + {0EBEE047-CBAD-4A69-8095-E3961B863446} = {7B739F28-21DE-435D-9EA6-579064932350} + {B4F76DF0-1638-42DA-B46A-30DC16AECEAB} = {7B739F28-21DE-435D-9EA6-579064932350} {DFC4F588-B4B4-484B-AB93-B36721374AD3} = {017429CC-C5FB-48B4-9C46-034E29EE2F06} {48FF1D87-5066-4294-B802-2D1B478C6EB6} = {DFC4F588-B4B4-484B-AB93-B36721374AD3} {563A3FFA-32DA-4ADA-891C-E00897BD919E} = {48FF1D87-5066-4294-B802-2D1B478C6EB6} @@ -8138,6 +8216,9 @@ Global {545751D5-71FC-4889-A3A0-BBD731DBA18A} = {56B45580-B089-424E-A847-A6115D591950} {E83B0BCC-A8E0-4FBD-BE51-9A533C9CB972} = {DFC4F588-B4B4-484B-AB93-B36721374AD3} {5D6F99C5-D292-4459-B8BD-8E4AD42E1B21} = {E83B0BCC-A8E0-4FBD-BE51-9A533C9CB972} + {CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1} = {5FE1FBC1-8CE3-4355-9866-44FE1307C5F1} + {C1CDD339-B51B-42BE-99F2-F39A4EC0D404} = {BB3D6EDD-AE71-4D25-B61B-7EBF7A1BA1D1} + {BB3D6EDD-AE71-4D25-B61B-7EBF7A1BA1D1} = {1A304CA0-7795-4684-88E5-E66402966927} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F} diff --git a/Directory.Build.props b/Directory.Build.props index 258a01d38823..4abbbfb80dc7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -87,12 +87,6 @@ $(MSBuildProjectDirectory) true - - - net5.0 net461 @@ -153,6 +147,7 @@ win-arm64; osx-x64; linux-musl-x64; + linux-musl-arm; linux-musl-arm64; linux-x64; linux-arm; diff --git a/NuGet.config b/NuGet.config index fdffb168b5f2..89fa2053af93 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,6 +10,8 @@ + + diff --git a/dockerbuild.sh b/dockerbuild.sh index ff24d88a9a4a..13366cc6faf9 100755 --- a/dockerbuild.sh +++ b/dockerbuild.sh @@ -136,6 +136,7 @@ docker run \ -e BUILD_BUILDID \ -e SYSTEM_TEAMPROJECT \ -e BUILD_BUILDNUMBER \ + -e BUILD_REPOSITORY_NAME \ -e BUILD_REPOSITORY_URI \ -e BUILD_REPOSITORY_NAME \ -e BUILD_SOURCEVERSION \ diff --git a/docs/BuildFromSource.md b/docs/BuildFromSource.md index 95858315fc09..886a012b3a79 100644 --- a/docs/BuildFromSource.md +++ b/docs/BuildFromSource.md @@ -1,154 +1,197 @@ # Build ASP.NET Core from Source -Building ASP.NET Core from source allows you to tweak and customize ASP.NET Core, and to contribute your improvements back to the project. +This document outlines how to build the source in the aspnetcore repo locally for development purposes. -See for known issues and to track ongoing work. +For more info on issues related to build infrastructure and ongoing work, see . -## Clone the source code +## Step 0: Getting started -ASP.NET Core uses git submodules to include the source from a few other projects. +This tutorial assumes that you are familiar with: -For a new copy of the project, run: +- Git +- Command line fundamentals in your operating system of choice + +## Step 1: Clone the source code + +ASP.NET Core uses git submodules to include the source from a few other projects. In order to pull the sources of the these submodules when cloning the repo, be sure to pass the `--recursive` flag to the `git clone` command. ```ps1 git clone --recursive https://github.com/dotnet/aspnetcore ``` -To update an existing copy, run: +If you've already cloned the aspnetcore repo without fetching subdmoule sources, you can fetch them after cloning by running the following command. ```ps1 git submodule update --init --recursive ``` -## Install pre-requisites +> :bulb: Some ISPs have been know to use web filtering software that has caused issues with git repository cloning, if you experience issues cloning this repo please review . -### Windows +## Step 2: Install pre-requisites -Building ASP.NET Core on Windows requires: +Developing in the aspnetcore repo requires some additional tools to build the source code and run integration tests. -* Windows 10, version 1803 or newer -* At least 10 GB of disk space and a good internet connection (our build scripts download a lot of tools and dependencies) -* Visual Studio 2019. - * To install the exact required components, run [eng/scripts/InstallVisualStudio.ps1](/eng/scripts/InstallVisualStudio.ps1). +### On Windows - ```ps1 - PS> ./eng/scripts/InstallVisualStudio.ps1 - ``` +Building ASP.NET Core on Windows (10, version 1803 or newer) requires that you have the following tooling installed. - However, any Visual Studio 2019 instance that meets the requirements should be fine. See [global.json](/global.json) - and [eng/scripts/vs.json](/eng/scripts/vs.json) for those requirements. By default, the script will install Visual Studio Enterprise Edition, however you can use a different edition by passing the `-Edition` flag. -* Git. -* NodeJS. LTS version of 10.14.2 or newer . -* Install yarn globally (`npm install -g yarn`) -* Java Development Kit 11 or newer. Either: - * OpenJDK - * Oracle's JDK - * To install a version of the JDK that will only be used by this repo, run [eng/scripts/InstallJdk.ps1](/eng/scripts/InstallJdk.ps1) +> :bulb: Be sure you have least 10 GB of disk space and a good Internet connection. The build scripts will download several tools and dependencies onto your machine. + +#### [Visual Studio 2019](https://visualstudio.com) - ```ps1 - PS> ./eng/scripts/InstallJdk.ps1 - ``` +Visual Studio 2019 (16.8) is required to build the repo locally. If you don't have visual studio installed you can run [eng/scripts/InstallVisualStudio.ps1](/eng/scripts/InstallVisualStudio.ps1) to install the exact required dependencies. + +> :bulb: By default, the script will install Visual Studio Enterprise Edition, however you can use a different edition by passing the `-Edition` flag. +> :bulb: To install Visual Studio from the preview channel, you can use the `-Channel` flag to set the channel (`-Channel Preview`). +> :bulb: Even if you have installed Visual Studio, we still recommend using this script to install again to avoid errors due to missing components. + +```ps1 +PS> ./eng/scripts/InstallVisualStudio.ps1 [-Edition {Enterprise|Community|Professional}] [-Channel {Release|Preview}] +``` - However, the build should find any JDK 11 or newer installation on the machine. - * Set the `JAVA_HOME` environment variable with the path of the java installation directory if your installation did not do that automatically. (Gradle needs this for execution.) - * This will be `RepoRoot/.tools/jdk/win-x64/` if you used the `InstallJdk.ps1` script - * This will be `C:/Program FIles/Java/jdk/` if you installed the JDK globally -* Chrome - Selenium-based tests require a version of Chrome to be installed. Download and install it from +> :bulb: To execute the setup script or other PowerShell scripts in the repo, you may need to update the execution policy on your machine. +> You can do so by running the `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` command +> in PowerShell. For more information on execution policies, you can read the [execution policy docs](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy). -### macOS/Linux +The [global.json](/global.json) file specifies the minimum requirements needed to build using `msbuild`. The [eng/scripts/vs.json](/eng/scripts/vs.json) file provides a description of the components needed to build within VS. If you plan on developing in Visual Studio, you will need to have these components installed. -Building ASP.NET Core on macOS or Linux requires: +> :bulb: The `IntallVisualStudio.ps1` script mentioned above reads from the `vs.json` file to determine what components to install. -* If using macOS, you need macOS Sierra or newer. -* If using Linux, you need a machine with all .NET Core Linux prerequisites: -* At least 10 GB of disk space and a good internet connection (our build scripts download a lot of tools and dependencies) -* curl or Wget -* Git -* NodeJS. LTS version of 10.14.2 or newer -* Java Development Kit 11 or newer. Either: +#### [Git](https://git-scm.org) + +If you're reading this, you probably already have Git installed to support cloning the repo as outlined in Step 1. + +#### [NodeJS](https://nodejs.org) + +Building the repo requires version 10.14.2 or newer of Node. You can find installation executables for Node at https://nodejs.org. + +#### [Yarn](https://yarnpkg.com/) + +NodeJS installes the Node package manager (npm) by default. This repo depends on yarn, an alternate package manager for the Node ecosystem. You can install Yarn from the command line using the following command. + +```ps1 +npm install -g yarn +``` + +#### Java Development Kit in Windows* + +This repo contains some Java source code that depends on an install of the JDK v11 or newer. The JDK can be installed from either: * OpenJDK * Oracle's JDK -**NOTE** some ISPs have been know to use web filtering software that has caused issues with git repository cloning, if you experience issues cloning this repo please review +Alternatively, you can run [eng/scripts/InstallJdk.ps1](/eng/scripts/InstallJdk.ps1) to install a version of the JDK that will only be used in this repo. -## Building in Visual Studio +```ps1 +PS> ./eng/scripts/InstallJdk.ps1 +``` -Before opening our .sln/.slnf files in Visual Studio or VS Code, you need to perform the following actions. +The build should find any JDK 11 or newer installation on the machine as long as the `JAVA_HOME` environment variable is set. Typically, your installation will do this automatically. However, if it is not set you can set the environment variable manually: + * Set `JAVA_HOME` to `RepoRoot/.tools/jdk/win-x64/` if you used the `InstallJdk.ps1` script. + * Set `JAVA_HOME` to `C:/Program Files/Java/jdk/` if you installed the JDK globally. -1. Executing the following on command-line: +#### Chrome - ```ps1 - .\restore.cmd - ``` +This repo contains a Selenium-based tests require a version of Chrome to be installed. Download and install it from . - This will download the required tools and build the entire repository once. At that point, you should be able - to open the .sln file or one of the project specific .slnf files to work on the projects you care about. +#### Wix (Optional) - > :bulb: Pro tip: you will also want to run this command after pulling large sets of changes. On the master - > branch, we regularly update the versions of .NET Core SDK required to build the repo. - > You will need to restart Visual Studio every time we update the .NET Core SDK. - > To allow executing the setup script, you may need to update the execution policy on your machine. - You can do so by running the `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` command - in PowerShell. For more information on execution policies, you can read the [execution policy docs](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy). +If you plan on working with the Windows installers defined in [src/Installers/Windows](../src/Installers/Windows), you will need to install the Wix toolkit from https://wixtoolset.org/releases/. -2. Use the `startvs.cmd` script to open Visual Studio .sln/.slnf files. This script first sets the required -environment variables. +### On macOS/Linux -### Solution files +You can also build ASP.NET Core on macOS or Linux. macOS Sierra or newer is required if you're building on macOS. If you're building on Linux, your machine will need to meet the [.NET Core Linux preequisities](https://docs.microsoft.com/en-us/dotnet/core/linux-prerequisites). -We have a single .sln file for all of ASP.NET Core, but most people don't work with it directly because Visual Studio -doesn't currently handle projects of this scale very well. +> :bulb: Be sure you have least 10 GB of disk space and a good Internet connection. The build scripts will download several tools and dependencies onto your machine. -Instead, we have many Solution Filter (.slnf) files which include a sub-set of projects. See the Visual Studio -documentation [here](https://docs.microsoft.com/en-us/visualstudio/ide/filtered-solutions?view=vs-2019) for more -information about Solution Filters. +#### curl/wget -These principles guide how we create and manage .slnf files: +`curl` and `wget` are command line tools that can be used to download files from an HTTP server. Either utility will need to be installed in order to complete the setup. Typically, these will be included on your machine by default. -1. Solution files are not used by CI or command line build scripts. They are meant for use by developers only. -2. Solution files group together projects which are frequently edited at the same time. -3. Can't find a solution that has the projects you care about? Feel free to make a PR to add a new .slnf file. +If netier utility is installed, you can install curl (https://curl.haxx.se) or wget (https://www.gnu.org/software/wget). -### Common error: CS0006 +##### Git -Opening solution filters and building may produce an error code CS0006 with a message such +If you've made it this far, you've already got `Git` installed. Sit back, relax, and move on to the next requirement. -> Error CS0006 Metadata file 'C:\src\aspnet\AspNetCore\artifacts\bin\Microsoft.AspNetCore.Metadata\Debug\netstandard2.0\Microsoft.AspNetCore.Metadata.dll' could not be found +#### [NodeJS](https://nodejs.org) -The cause of this problem is that the solution filter you are using does not include the project that produces this .dll. This most often occurs after we have added new projects to the repo, but failed to update our .sln/slnf files to include the new project. In some cases, it is sometimes the intended behavior of the .slnf which has been crafted to only include a subset of projects. +Building the repo requires version 10.14.2 or newer of Node. You can find installation executables for Node at https://nodejs.org. -#### You can fix this in one of three ways +#### [Yarn](https://yarnpkg.com/) -1. Build the project on command line. In most cases, running `build.cmd` on command line solves this problem. -2. If the project is missing from the .sln file entirely, you can use `dotnet sln add` to add it, or else right click on the solution/folder in Visual Studio and choose Add->Existing Project, and adding it. -3. If it is present in the .sln, but not the .slnf, you can update the solution filter to include the missing project. You can either do this one by right-clicking on project in Visual Studio and choosing to load it's direct dependencies, and then saving. Alternatively, you can hand edit the .slnf file - it's a fairly simple json format. +NodeJS installs the Node package manager (npm) by default. This repo depends on yarn, an alternate package manager for the Node ecosystem. You can install Yarn from the command line using the following command. -### Common error: Unable to locate the .NET Core SDK +```bash +$ npm install -g yarn +``` -Executing `.\restore.cmd` or `.\build.cmd` may produce these errors: +#### Java Development Kit -> error : Unable to locate the .NET Core SDK. Check that it is installed and that the version specified in global.json (if any) matches the installed version. -> error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. +This repo contains some Java source code that depends on an install of the JDK v11 or newer. The JDK can be installed from either: + * OpenJDK + * Oracle's JDK -In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_. +Similar to [the instructions above for Windows](#java-development-kit-in-windows), be sure that the the `JAVA_HOME` environment variable is set to the location of your Java installation. -### Common error: HTTP Error 500.33 - ANCM Request Handler Load Failure +## Step 3: Build the repo -The [ASP.NET Core Module](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module) (ANCM) for IIS is not supported when running projects in this repository. +Before opening our .sln/.slnf files in Visual Studio or VS Code, you will need to build the repo locally. -After using `startvs.cmd` to open a solution in Visual Studio, the Kestrel web host option must be used (name of the project) and not IIS Express. +### In Visual Studio -Example of running the `MvcSandbox` project: +To set up your project for development on Visual Studio, you'll need to execute the following command. -`.\startvs.cmd .\src\Mvc\Mvc.sln` +```ps1 +PS1> .\restore.cmd +``` -![Web host options in Visual Studio](./vs-iis-express-aspnet-core-mvc-sandbox.jpg) +> :bulb: If you happen to be working on macOS or Linux, you can use the `restore.sh` command. + +This will download the required tools and restore all projects inside the repository. At that point, you should be able +to open the .sln file or one of the project specific .slnf files to work on the projects you care about. + + > :bulb: Pro tip: you will also want to run this command after pulling large sets of changes. On the master + > branch, we regularly update the versions of .NET Core SDK required to build the repo. + > You will need to restart Visual Studio every time we update the .NET Core SDK. + +Typically, you want to focus on a single project within the monorepo. For example, +if you want to work on Blazor WebAssembly, you'll need to launch the solution file for that project by changing into the `src/Components` +directory and executing `startvs.cmd` in that directory like so: + +```ps1 +PS1> cd src\Components +PS1> .\startvs.cmd +``` + +After opening the solution in Visual Studio, you can build/rebuild using the controls in Visual Studio. + +> :exclamation: VS for Mac does not currently support opening .slnf files so you must use VS Code when developing on macOS. + +#### A brief interlude on solution files + +We have a single .sln file for all of ASP.NET Core, but most people don't work with it directly because Visual Studio +doesn't currently handle projects of this scale very well. + +Instead, we have many Solution Filter (.slnf) files which include a sub-set of projects. See the Visual Studio +documentation [here](https://docs.microsoft.com/en-us/visualstudio/ide/filtered-solutions?view=vs-2019) for more +information about Solution Filters. + +These principles guide how we create and manage .slnf files: + +1. Solution files are not used by CI or command line build scripts. They are meant for use by developers only. +2. Solution files group together projects which are frequently edited at the same time. +3. Can't find a solution that has the projects you care about? Feel free to make a PR to add a new .slnf file. -## Building with Visual Studio Code +### In Visual Studio Code + +Before opening the project in Visual Studio Code, you will need to make sure that you have built the project. +You can find more info on this in the "Building on command-line" section below. Using Visual Studio Code with this repo requires setting environment variables on command line first. Use these command to launch VS Code with the right settings. +> :bulb: Note that you'll need to launch Visual Studio Code from the command line in order to ensure that it picks up the environment variables. To learn more about the Visual Studio Code CLI, you can check out [the docs page](https://code.visualstudio.com/docs/editor/command-line). + On Windows (requires PowerShell): ```ps1 @@ -165,14 +208,14 @@ source activate.sh code . ``` -Note that if you are using the "Remote-WSL" extension in VSCode, the environment is not supplied -to the process in WSL. You can workaround this by explicitly setting the environment variables -in `~/.vscode-server/server-env-setup`. -See https://code.visualstudio.com/docs/remote/wsl#_advanced-environment-setup-script for details. +> :bulb: Note that if you are using the "Remote-WSL" extension in VSCode, the environment is not supplied +> to the process in WSL. You can workaround this by explicitly setting the environment variables +> in `~/.vscode-server/server-env-setup`. +> See https://code.visualstudio.com/docs/remote/wsl#_advanced-environment-setup-script for details. ## Building on command-line -You can also build the entire project on command line with the `build.cmd`/`.sh` scripts. +When developing in VS Code, you'll need to use the `build.cmd` or `build.sh` scripts in order to build the project. You can learn more about the command line options available, check out [the section below](using-dotnet-on-command-line-in-this-repo). On Windows: @@ -188,10 +231,16 @@ On macOS/Linux: By default, all of the C# projects are built. Some C# projects require NodeJS to be installed to compile JavaScript assets which are then checked in as source. If NodeJS is detected on the path, the NodeJS projects will be compiled as part of building C# projects. If NodeJS is not detected on the path, the JavaScript assets checked in previously will be used instead. To disable building NodeJS projects, specify `-noBuildNodeJS` or `--no-build-nodejs` on the command line. -### Using `dotnet` on command line in this repo +## Step 4: Make your code changes + +At this point, you will have all the dependencies installed and a code editor to up and running to make changes in. Once you've made changes, you will need to rebuild the project locally to pick up your changes. You'll also need to run tests locally to verify that your changes worked. + +The section below provides some helpful guides for using the `dotnet` CLI in the ASP.NET Core repo. + +## Using `dotnet` on command line in this repo Because we are using pre-release versions of .NET Core, you have to set a handful of environment variables -to make the .NET Core command line tool work well. You can set these environment variables like this +to make the .NET Core command line tool work well. You can set these environment variables like this: On Windows (requires PowerShell): @@ -207,7 +256,9 @@ On macOS/Linux: source ./activate.sh ``` -## Running tests on command-line +> :bulb: Be sure to set the environment variables using the "activate" script above before executing the `dotnet` command inside the repo. + +### Running tests on command-line Tests are not run by default. Use the `-test` option to run tests in addition to building. @@ -223,13 +274,15 @@ On macOS/Linux: ./build.sh --test ``` -## Building a subset of the code +> :bulb: If you're working on changes for a particular subset of the project, you might not want to execute the entire test suite. Instead, only run the tests within the subdirectory where changes were made. This can be accomplished by passing the `projects` property like so: `.\build.cmd -test -projects .\src\Framework\test\Microsoft.AspNetCore.App.UnitTests.csproj`. + +### Building a subset of the code This repository is large. Look for `build.cmd`/`.sh` scripts in subfolders. These scripts can be used to invoke build and test on a smaller set of projects. Furthermore, you can use flags on `build.cmd`/`.sh` to build subsets based on language type, like C++, TypeScript, or C#. Run `build.sh --help` or `build.cmd -help` for details. -## Build properties +### Build properties Additional properties can be added as an argument in the form `/property:$name=$value`, or `/p:$name=$value` for short. For example: @@ -245,7 +298,7 @@ Configuration | `Debug` or `Release`. Default = `Debug`. TargetArchitecture | The CPU architecture to build for (x64, x86, arm, arm64). TargetOsName | The base runtime identifier to build for (win, linux, osx, linux-musl). -## Use the result of your build +### Use the result of your build After building ASP.NET Core from source, you will need to install and use your local version of ASP.NET Core. See ["Artifacts"](./Artifacts.md) for more explanation of the different folders produced by a build. @@ -289,4 +342,53 @@ These are available in the [Visual Studio Preview](https://www.visualstudio.com/ ## Resx files -If you need to make changes to a .resx file, run `dotnet msbuild /t:Resx `. This will update the generated C#. +If you need to make changes to a .resx file, run `dotnet msbuild t:/Resgen `. This will update the generated C#. + +## Troubleshooting + +This section contains a troubleshooting guide for common issues you might run into while building the repo. + +### Common error: CS0006 + +Opening solution filters and building may produce an error code CS0006 with a message such + +> Error CS0006 Metadata file 'C:\src\aspnet\AspNetCore\artifacts\bin\Microsoft.AspNetCore.Metadata\Debug\netstandard2.0\Microsoft.AspNetCore.Metadata.dll' could not be found + +The cause of this problem is that the solution filter you are using does not include the project that produces this .dll. This most often occurs after we have added new projects to the repo, but failed to update our .sln/slnf files to include the new project. In some cases, it is sometimes the intended behavior of the .slnf which has been crafted to only include a subset of projects. + +#### You can fix this in one of three ways + +1. Build the project on command line. In most cases, running `build.cmd` on command line solves this problem. +2. If the project is missing from the .sln file entirely, you can use `dotnet sln add` to add it, or else right click on the solution/folder in Visual Studio and choose Add->Existing Project, and adding it. +3. If it is present in the .sln, but not the .slnf, you can update the solution filter to include the missing project. You can either do this one by right-clicking on project in Visual Studio and choosing to load it's direct dependencies, and then saving. Alternatively, you can hand edit the .slnf file - it's a fairly simple json format. + +### Common error: Unable to locate the .NET Core SDK + +Executing `.\restore.cmd` or `.\build.cmd` may produce these errors: + +> error : Unable to locate the .NET Core SDK. Check that it is installed and that the version specified in global.json (if any) matches the installed version. +> error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. + +In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_. + +### Common error: HTTP Error 500.33 - ANCM Request Handler Load Failure + +The [ASP.NET Core Module](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module) (ANCM) for IIS is not supported when running projects in this repository. + +After using `startvs.cmd` to open a solution in Visual Studio, the Kestrel web host option must be used (name of the project) and not IIS Express. + +Example of running the `MvcSandbox` project: + +`.\startvs.cmd .\src\Mvc\Mvc.sln` + +![Web host options in Visual Studio](./vs-iis-express-aspnet-core-mvc-sandbox.jpg) + +### Common error: error : Unable to load the service index for … + +When attempting to restore servicing tags e.g. `v3.1.7`, the NuGet.config file may contain internal feeds that are not accessible. This will result in errors such as + +``` text +...\aspnetcore\.dotnet\sdk\3.1.103\NuGet.targets(123,5): error : Unable to load the service index for source https://pkgs.dev.azure.com/dnceng/_packaging/darc-int-dotnet-extensions-784b0ffa/nuget/v3/index.json. [...\Temp\1gsd3rdo.srb\restore.csproj] [...\.nuget\packages\microsoft.dotnet.arcade.sdk\1.0.0-beta.20213.4\tools\Tools.proj] +``` + +The `darc-int-...` feeds in NuGet.config are used only when building internally and are not needed after the tags are created. Delete all such entries in the file and retry. diff --git a/docs/PackageArchives.md b/docs/PackageArchives.md deleted file mode 100644 index 420e0906dfba..000000000000 --- a/docs/PackageArchives.md +++ /dev/null @@ -1,62 +0,0 @@ -Package Archives -================ - -This repo builds multiple package archives which contain a NuGet fallback folder (also known as the fallback or offline package cache). The fallback folder is a set of NuGet packages that is bundled in the .NET Core SDK installers and available in Azure Web App service. - -Package archives are available in four varieties. - -* **LZMA** - `nuGetPackagesArchive-$(Version).lzma` - The LZMA is a compressed file format, similar to a .zip. On first use or on install, the .NET Core CLI will expand this LZMA file, extracting the packages inside to %DOTNET_INSTALL_DIR%/sdk/NuGetFallbackFolder. This contains all NuGet packages and their complete contents. -* **ci-server** - `nuGetPackagesArchive-ci-server-$(Version).zip` - this archive is optimized for CI server environments. It contains the same contents as the LZMA, but trimmed of xml docs (these are only required for IDEs) and .nupkg files (not required for NuGet as for the 2.0 SDK). -* **ci-server-patch** - `nuGetPackagesArchive-ci-server-$(Version).patch.zip` - this archive is the same as the ci-server archive, but each release is incremental - i.e. it does not bundle files that were present in a previous ci-server archive release. This can be used by first starting with a baseline `nuGetPackagesArchive-ci-server-$(Version).zip` and then applying the `.patch.zip` version for subsequent updates. -* **ci-server-compat-patch** - `nuGetPackagesArchive-ci-server-compat-$(Version).patch.zip` - similar to the ci-server-patch archive, but this includes .nupkg files to satisfy CI environments that may have older NuGet clients. - -These archives are built using the projects in [src/PackageArchive/Archive.\*/](/src/PackageArchive/). - -## Using a fallback folder - -NuGet restore takes a list of fallback folders in the MSBuild property `RestoreAdditionalProjectFallbackFolders`. Unlike a folder restore source, restore will not copy the packages from a fallback folder into the global NuGet cache. - -By default, the .NET Core SDK adds `$(DotNetInstallRoot)/sdk/NuGetFallbackFolder/` to this list. The .NET Core CLI expands its bundled `nuGetPackagesArchive.lzma` file into this location on first use or when the installers run. (See [Microsoft.NET.NuGetOfflineCache.targets](https://github.com/dotnet/sdk/blob/v2.1.300/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.NuGetOfflineCache.targets)). - -## Scenarios - -The following scenarios are used to determine which packages go into the fallback package cache. -These requirements are formalized as project files in [src/PackageArchive/Scenario.\*/](/src/PackageArchive/). - - - A user should be able to restore the following templates and only use packages from the offline cache: - - `dotnet new console` - - `dotnet new library` - - `dotnet new web` - - `dotnet new razor` - - `dotnet new mvc` - -The following packages are NOT included in the offline cache. - - Packages required for standalone publishing, aka projects that set a Runtime Identifier during restore - - Packages required for F# and VB templates - - Packages required for Visual Studio code generation in ASP.NET Core projects - - Packages required to restore .NET Framework projects - - Packages required to restore test projects, such as xunit, MSTest, NUnit - -The result of this typically means including the transitive graph of the following packages: - - - Packages that match bundled runtimes - - Microsoft.NETCore.App - - Microsoft.AspNetCore.App - - Packages that Microsoft.NET.Sdk adds implicitly - - Microsoft.NETCore.App - - NETStandard.Library - -### Example - -Given the following parameters: - - LatestNETCoreAppTFM = netcoreapp2.1 - - DefaultRuntimeVersion = 2.1 - - BundledRuntimeVersion = 2.1.8 - - BundledAspNetRuntimeVersion = 2.1.7 - - LatestNETStandardLibraryTFM = netstandard2.0 - - BundledNETStandardLibraryVersion = 2.0.1 - -The LZMA should contain - - Microsoft.NETCore.App/2.1.0 + netcoreapp2.1 dependencies (Microsoft.NET.Sdk will implicitly reference "2.1", which NuGet to 2.1.0) - - Microsoft.NETCore.App/2.1.8 + netcoreapp2.1 dependencies (Matches the runtime in shared/Microsoft.NETCore.App/2.1.8/) - - NETStandard.Library/2.0.1 + netstandard2.0 dependencies (Microsoft.NET.Sdk will implicitly reference "2.0.1") diff --git a/docs/README.md b/docs/README.md index 230b8d7f5173..67400982b4dd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,8 +4,23 @@ Contributor documentation The primary audience for documentation in this folder is contributors to ASP.NET Core. If you are looking for documentation on how to *use* ASP.NET Core, go to . -# ASP.NET Core developer workflow +> :bulb: If you're a new contributor looking to set up the repo locally, the [build from source documentation](BuildFromSource.md) is the best place to start. -- [Building from source](BuildFromSource.md) -- [Troubleshooting build errors](BuildErrors.md) -- [Artifacts structure](Artifacts.md) +The table below outlines the different docs in this folder and what they are helpful for. + +| Documentation | What is it about? | Who is it for? | +|--------------------------------------------------------------------------|-------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| +| [API review process](APIReviewProcess.md) | Outlines the process for reviewing API changes in ASP.NET Core | Anyone looking to understand the process for making API changes to ASP.NET Core | +| [Artifacts structure](Artifacts.md) | Outlines the artifacts produced by the build | Anyone looking to understand artifiacts produced from an Azure DevOps build | +| [Troubleshooting build errors](BuildErrors.md) | Common errors that occur when building the repo and how to resolve them | Anyone running into an issue with the build | +| [Building from source](BuildFromSource.md) | Setup instructions for the ASP.NET Core repo | First-time contributors | +| [Working with EventSources and EventCounters](EventSourceAndCounters.md) | Guidance on adding event tracing to a library | Anyone needing to add event tracing for diagnostics purposes | +| [Tests on Helix](Helix.md) | An overview of the Helix test environment | Anyone debugging tests in Helix or looking to understand the output from Helix builds | +| [Issue management](IssueManagementPolicies.md) | Overview of policies in place to manage issues| Community members and collaborators looking to understand how we handle closed issue, issues that need author feedback, etc | | +| [Preparing a patch update](PreparingPatchUpdates.md) | Documentation on how to setup for a patch release of ASP.NET Core | Anyone looking to publish servicing updates | +| [Project properties](ProjectProperties.md) | Overview of configurable MSBuild properties on the repo | Anyone looking to modify how a project is packaged | +| [How references are resolved](ReferenceResolution.md) | Overview of dependency reference setup in the repo | Anyone looking to understand how package references are configured in the repo | +| [Servicing changes](Servicing.md) | Documentation on how to submit servicing PRs to previous releases | Anyone to submit patches or backports to prior releases, contains the "Shiproom Template" | +| [Shared framework](SharedFramework.md) | Overview of the ASP.NET Core Shared framework | Anyone looking to understand the policies in place for managing the code of the shared framework | +| Submodules | Documentation on working with submodules in Git | Anyone working with submodules in the repo | +| [Triage process](TriageProcess.md)| Overview of the issue triage process used in the repo | Anyone looking to understand the triage process on the repo | diff --git a/docs/TriageProcess.md b/docs/TriageProcess.md index 0d9577e45831..61955f123cdc 100644 --- a/docs/TriageProcess.md +++ b/docs/TriageProcess.md @@ -53,7 +53,7 @@ We may not investigate issues which haven't received many votes/comments and cho For some feature requests and bug reports, depending on the user involvement, we may choose to move these to the backlog at this point. What this means, is that they will not be looked at again up until the next major release planning. ## Release Planning -Once we approach to the end of the release cylce (.NET Core 3, .NET 5) we will look through the accumulated issues in the `Backlog` milestone. This is a long process as the amount of issues accumulated in this milestone is quite large. +Once we approach to the end of the release cycle (.NET Core 3, .NET 5) we will look through the accumulated issues in the `Backlog` milestone. This is a long process as the amount of issues accumulated in this milestone is quite large. We will try to prioritize issues with most community requests / upvotes assuming these are aligned with our goals. Issues, which we will think are candidates for the upcoming release, will be moved to the `Next Sprint Planning` milestone. diff --git a/docs/area-owners.md b/docs/area-owners.md index e4d6e72071e0..de68f8183151 100644 --- a/docs/area-owners.md +++ b/docs/area-owners.md @@ -2,22 +2,21 @@ The below table lists all the `area-`labels used in the `aspnetcore` repository | Area label | Owner | Description| |--- | ---| --- | -| area-azure | anurse | | +| area-azure | BrennanConroy | | | area-blazor | mkArtakMSFT | Blazor server and Blazor WASM related | -| area-commandlinetools | anurse, mkArtakMSFT | dev certs, dotnet watch, | -| area-dataprotection | anurse | | +| area-commandlinetools | mkArtakMSFT | dev certs, dotnet watch, | +| area-dataprotection | Pilchie | | | area-grpc | shirhatti | | -| area-healthchecks | rynowak | | -| area-hosting | anurse | | -| area-httpclientfactory | anurse | | +| area-healthchecks | mkArtakMSFT | | +| area-hosting | BrennanConroy | | | area-identity | blowdart | | | area-infrastructure | dougbu | | -| area-installers | anurse | | -| area-middleware | anurse | | +| area-installers | dougbu | | +| area-middleware | BrennanConroy | | | area-mvc | mkArtakMSFT | | -| area-perf | anurse | | -| area-platform | anurse | | +| area-perf | sebastienros | | +| area-platform | JunTaoLuo | | | area-security | blowdart | | -| area-servers | anurse | | -| area-signalr | anurse | | -| area-websockets | anurse | | +| area-servers | BrennanConroy | | +| area-signalr | BrennanConroy | | +| area-websockets | BrennanConroy | | diff --git a/eng/AfterSolutionBuild.targets b/eng/AfterSolutionBuild.targets index 4a3cb4ba2adf..5c2989479709 100644 --- a/eng/AfterSolutionBuild.targets +++ b/eng/AfterSolutionBuild.targets @@ -15,7 +15,7 @@ + SharedFrameworkTargetFramework="$(DefaultNetCoreTargetFramework)" /> diff --git a/eng/Baseline.Designer.props b/eng/Baseline.Designer.props index d3894b52f088..d1991880ab97 100644 --- a/eng/Baseline.Designer.props +++ b/eng/Baseline.Designer.props @@ -2,7 +2,7 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 3.1.7 + 3.1.8 @@ -14,7 +14,7 @@ - 3.1.7 + 3.1.8 @@ -25,83 +25,83 @@ - 3.1.7 + 3.1.8 - - - + + + - + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 @@ -109,97 +109,97 @@ - 3.1.7 + 3.1.8 - - - + + + - - - + + + - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - - - + + + - - - + + + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - - + + - - + + - 3.1.7 + 3.1.8 - + - + - 3.1.7 + 3.1.8 - - - - + + + + - - - - + + + + @@ -244,215 +244,215 @@ - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 - - + + - + - + - - + + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - + - + - + - 3.1.7 + 3.1.8 - - - - - - + + + + + + - - - - - - + + + + + + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 - - + + - - + + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - - - + + + - - - + + + - 3.1.7 + 3.1.8 - + - + - 3.1.7 + 3.1.8 - - + + - - + + - 3.1.7 + 3.1.8 - - + + - - + + - 3.1.7 + 3.1.8 - - - + + + - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 @@ -460,236 +460,236 @@ - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - - - + + + - 3.1.7 + 3.1.8 - - - + + + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - + - - + + - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 - - + + - - + + - - - - + + + + - 3.1.7 + 3.1.8 - - + + - - + + - 3.1.7 + 3.1.8 - + - + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - - - - + + + + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - - + + - 3.1.7 + 3.1.8 - + - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - 3.1.7 + 3.1.8 - - - + + + - 3.1.7 + 3.1.8 - - - + + + - - - + + + - 3.1.7 + 3.1.8 - - - + + + - - - + + + \ No newline at end of file diff --git a/eng/Baseline.xml b/eng/Baseline.xml index ca3b6217b81f..ce5a601fe356 100644 --- a/eng/Baseline.xml +++ b/eng/Baseline.xml @@ -4,87 +4,87 @@ This file contains a list of all the packages and their versions which were rele Update this list when preparing for a new patch. --> - + - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eng/Dependencies.props b/eng/Dependencies.props index 62a7ac2e0f82..a0acb2d7924b 100644 --- a/eng/Dependencies.props +++ b/eng/Dependencies.props @@ -94,15 +94,17 @@ and are generated based on the last package release. + - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c58297de2d69..3fa9dd819fee 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,304 +9,309 @@ --> - + https://github.com/dotnet/efcore - 69c4c9d142882c71cf196d593a1786180abee181 + 2352499b52cdfc95ddcfd81c4967e12512e00eee - + https://github.com/dotnet/efcore - 69c4c9d142882c71cf196d593a1786180abee181 + 2352499b52cdfc95ddcfd81c4967e12512e00eee - + https://github.com/dotnet/efcore - 69c4c9d142882c71cf196d593a1786180abee181 + 2352499b52cdfc95ddcfd81c4967e12512e00eee - + https://github.com/dotnet/efcore - 69c4c9d142882c71cf196d593a1786180abee181 + 2352499b52cdfc95ddcfd81c4967e12512e00eee - + https://github.com/dotnet/efcore - 69c4c9d142882c71cf196d593a1786180abee181 + 2352499b52cdfc95ddcfd81c4967e12512e00eee - + https://github.com/dotnet/efcore - 69c4c9d142882c71cf196d593a1786180abee181 + 2352499b52cdfc95ddcfd81c4967e12512e00eee - + https://github.com/dotnet/efcore - 69c4c9d142882c71cf196d593a1786180abee181 + 2352499b52cdfc95ddcfd81c4967e12512e00eee - + https://github.com/dotnet/efcore - 69c4c9d142882c71cf196d593a1786180abee181 + 2352499b52cdfc95ddcfd81c4967e12512e00eee - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa + + + https://github.com/dotnet/runtime + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa - + https://github.com/dotnet/runtime - 2d8e19f1880c655bcc0994852f41b47341e2c566 + 4fef87c65e7466000884aeb9dee6498b162fe2fa https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index b632a8647139..466319ae7906 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -6,33 +6,38 @@ --> - 5 + 6 0 0 + 1 true release - rtm - RTM $(PreReleaseVersionIteration) + alpha + Alpha $(PreReleaseVersionIteration) true false $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) true - $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion) + $(AspNetCoreMajorMinorVersion).$(AspNetCorePatchVersion) $(VersionPrefix) - $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).0 + $(AspNetCoreMajorMinorVersion).0 0.3.$(AspNetCorePatchVersion) $([MSBuild]::Add(10, $(AspNetCoreMajorVersion))) $(AspNetCoreMinorVersion) $(AspNetCorePatchVersion) - $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$([MSBuild]::Subtract($(AspNetCorePatchVersion), 1)) + $(AspNetCoreMajorMinorVersion).$([MSBuild]::Subtract($(AspNetCorePatchVersion), 1)) + + net5.0 @@ -54,81 +59,83 @@ --> - 5.0.0 - 5.0.0-rtm.20514.6 - 5.0.0 - 5.0.0 - 5.0.0-rtm.20514.6 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0-rtm.20514.6 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0-rtm.20514.6 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 + 6.0.0-alpha.1.20507.4 - 5.0.0 + 6.0.0-alpha.1.20507.4 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 - 5.0.0 + 6.0.0-alpha.1.20509.5 + 6.0.0-alpha.1.20509.5 + 6.0.0-alpha.1.20509.5 + 6.0.0-alpha.1.20509.5 + 6.0.0-alpha.1.20509.5 + 6.0.0-alpha.1.20509.5 + 6.0.0-alpha.1.20509.5 + 6.0.0-alpha.1.20509.5 5.0.0-beta.20510.1 @@ -149,6 +156,7 @@ $(MicrosoftNETCoreAppRuntimewinx64PackageVersion) + 3.8.0-3.20458.6 5.0.0-preview.4.20180.4 @@ -197,12 +205,15 @@ 1.4.0 6.7.1 5.7.0 - + 2.1.1 2.2.0 3.1.8-servicing-20421-6 $(MicrosoftAspNetCoreAzureAppServicesSiteExtension31PackageVersion) $(MicrosoftAspNetCoreAzureAppServicesSiteExtension31PackageVersion) + 5.0.0-preview-7-20365-19 + $(MicrosoftAspNetCoreAzureAppServicesSiteExtension50PackageVersion) + $(MicrosoftAspNetCoreAzureAppServicesSiteExtension50PackageVersion) 0.9.9 0.12.1 @@ -231,7 +242,7 @@ 13.0.4 4.0.0-alpha05 17.17134.0 - 85.0.4183.8300 + 86.0.4240.2200-beta 4.0.0-alpha05 1.4.0 4.0.0 diff --git a/eng/helix/content/RunTests/RunTestsOptions.cs b/eng/helix/content/RunTests/RunTestsOptions.cs index 13bd50a80fad..031326ba8a14 100644 --- a/eng/helix/content/RunTests/RunTestsOptions.cs +++ b/eng/helix/content/RunTests/RunTestsOptions.cs @@ -50,6 +50,11 @@ public static RunTestsOptions Parse(string[] args) aliases: new string[] { "--helixTimeout" }, description: "The timeout duration of the Helix job") { Argument = new Argument(), Required = true }, + + new Option( + aliases: new string[] { "--source" }, + description: "The restore sources to use during testing") + { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore }, Required = true } }; var parseResult = command.Parse(args); diff --git a/eng/targets/Helix.Common.props b/eng/targets/Helix.Common.props index 07b8246029c9..87efd43249d0 100644 --- a/eng/targets/Helix.Common.props +++ b/eng/targets/Helix.Common.props @@ -21,25 +21,29 @@ - + - - - - + + + + + + + + + - diff --git a/eng/tools/BaselineGenerator/BaselineGenerator.csproj b/eng/tools/BaselineGenerator/BaselineGenerator.csproj index 775e7523c847..d80ea1277248 100644 --- a/eng/tools/BaselineGenerator/BaselineGenerator.csproj +++ b/eng/tools/BaselineGenerator/BaselineGenerator.csproj @@ -7,8 +7,8 @@ + - diff --git a/eng/tools/BaselineGenerator/Program.cs b/eng/tools/BaselineGenerator/Program.cs index e77b35edeeeb..a68406a3cd68 100644 --- a/eng/tools/BaselineGenerator/Program.cs +++ b/eng/tools/BaselineGenerator/Program.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Linq; +using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading; @@ -30,16 +31,18 @@ static void Main(string[] args) new Program().Execute(args); } - private readonly CommandOption _source; + private readonly CommandOption _sources; private readonly CommandOption _output; private readonly CommandOption _update; + private static readonly string[] _defaultSources = new string[] { "https://api.nuget.org/v3/index.json" }; + public Program() { - _source = Option( - "-s|--package-source ", - "The NuGet source of packages to fetch", - CommandOptionType.SingleValue); + _sources = Option( + "-s|--package-sources ", + "The NuGet source(s) of packages to fetch", + CommandOptionType.MultipleValue); _output = Option("-o|--output ", "The generated file output path", CommandOptionType.SingleValue); _update = Option("-u|--update", "Regenerate the input (Baseline.xml) file.", CommandOptionType.NoValue); @@ -56,26 +59,32 @@ private async Task Run() var inputPath = Path.Combine(Directory.GetCurrentDirectory(), "Baseline.xml"); var input = XDocument.Load(inputPath); - var source = _source.HasValue() ? _source.Value().TrimEnd('/') : "https://api.nuget.org/v3/index.json"; - var packageSource = new PackageSource(source); + var sources = _sources.HasValue() ? _sources.Values.Select(s => s.TrimEnd('/')) : _defaultSources; + var packageSources = sources.Select(s => new PackageSource(s)); var providers = Repository.Provider.GetCoreV3(); // Get v2 and v3 API support - var sourceRepository = new SourceRepository(packageSource, providers); + var sourceRepositories = packageSources.Select(ps => new SourceRepository(ps, providers)); if (_update.HasValue()) { - var updateResult = await RunUpdateAsync(inputPath, input, sourceRepository); + var updateResult = await RunUpdateAsync(inputPath, input, sourceRepositories); if (updateResult != 0) { return updateResult; } } - var feedType = await sourceRepository.GetFeedType(CancellationToken.None); - var feedV3 = feedType == FeedType.HttpV3; - var packageBase = source + "/package"; - if (feedV3) + List<(string packageBase, bool feedV3)> packageBases = new List<(string, bool)>(); + foreach (var sourceRepository in sourceRepositories) { - var resources = await sourceRepository.GetResourceAsync(); - packageBase = resources.GetServiceEntryUri(ServiceTypes.PackageBaseAddress).ToString().TrimEnd('/'); + var feedType = await sourceRepository.GetFeedType(CancellationToken.None); + var feedV3 = feedType == FeedType.HttpV3; + var packageBase = sourceRepository.PackageSource + "/package"; + if (feedV3) + { + var resources = await sourceRepository.GetResourceAsync(); + packageBase = resources.GetServiceEntryUri(ServiceTypes.PackageBaseAddress).ToString().TrimEnd('/'); + } + + packageBases.Add((packageBase, feedV3)); } var output = _output.HasValue() @@ -116,18 +125,34 @@ private async Task Run() if (!File.Exists(nupkgPath)) { - var url = feedV3 ? - $"{packageBase}/{id.ToLowerInvariant()}/{version}/{id.ToLowerInvariant()}.{version}.nupkg" : - $"{packageBase}/{id}/{version}"; - - Console.WriteLine($"Downloading {url}"); - using (var response = await client.GetStreamAsync(url)) + foreach ((string packageBase, bool feedV3) in packageBases) { - using (var file = File.Create(nupkgPath)) + var url = feedV3 ? + $"{packageBase}/{id.ToLowerInvariant()}/{version}/{id.ToLowerInvariant()}.{version}.nupkg" : + $"{packageBase}/{id}/{version}"; + + Console.WriteLine($"Downloading {url}"); + try + { + using (var response = await client.GetStreamAsync(url)) + { + using (var file = File.Create(nupkgPath)) + { + await response.CopyToAsync(file); + } + } + } + catch (HttpRequestException e) when (e.StatusCode == System.Net.HttpStatusCode.NotFound) { - await response.CopyToAsync(file); + // If it's not found, continue onto the next one. + continue; } } + + if (!File.Exists(nupkgPath)) + { + throw new Exception($"Could not download package {id} @ {version} using any input feed"); + } } using (var reader = new PackageArchiveReader(nupkgPath)) @@ -195,9 +220,11 @@ private async Task Run() private async Task RunUpdateAsync( string documentPath, XDocument document, - SourceRepository sourceRepository) + IEnumerable sourceRepositories) { - var packageMetadataResource = await sourceRepository.GetResourceAsync(); + var packageMetadataResources = await Task.WhenAll(sourceRepositories.Select(async sr => + await sr.GetResourceAsync())); + var logger = new Logger(Error, Out); var hasChanged = false; using (var cacheContext = new SourceCacheContext { NoCache = true }) @@ -206,7 +233,7 @@ private async Task RunUpdateAsync( hasChanged = await TryUpdateVersionAsync( versionAttribute, "Microsoft.AspNetCore.App.Runtime.win-x64", - packageMetadataResource, + packageMetadataResources, logger, cacheContext); @@ -217,7 +244,7 @@ private async Task RunUpdateAsync( var attributeChanged = await TryUpdateVersionAsync( versionAttribute, id, - packageMetadataResource, + packageMetadataResources, logger, cacheContext); @@ -261,25 +288,36 @@ private async Task RunUpdateAsync( private static async Task TryUpdateVersionAsync( XAttribute versionAttribute, string packageId, - PackageMetadataResource packageMetadataResource, + IEnumerable packageMetadataResources, ILogger logger, SourceCacheContext cacheContext) { - var searchMetadata = await packageMetadataResource.GetMetadataAsync( - packageId, - includePrerelease: false, - includeUnlisted: true, // Microsoft.AspNetCore.DataOrotection.Redis package is not listed. - sourceCacheContext: cacheContext, - log: logger, - token: CancellationToken.None); - var currentVersion = NuGetVersion.Parse(versionAttribute.Value); var versionRange = new VersionRange( currentVersion, new FloatRange(NuGetVersionFloatBehavior.Patch, currentVersion)); - var latestVersion = versionRange.FindBestMatch( - searchMetadata.Select(metadata => metadata.Identity.Version)); + var searchMetadatas = await Task.WhenAll( + packageMetadataResources.Select(async pmr => await pmr.GetMetadataAsync( + packageId, + includePrerelease: false, + includeUnlisted: true, // Microsoft.AspNetCore.DataOrotection.Redis package is not listed. + sourceCacheContext: cacheContext, + log: logger, + token: CancellationToken.None))); + + // Find the latest version among each search metadata + NuGetVersion latestVersion = null; + foreach (var searchMetadata in searchMetadatas) + { + var potentialLatestVersion = versionRange.FindBestMatch( + searchMetadata.Select(metadata => metadata.Identity.Version)); + if (latestVersion == null || + (potentialLatestVersion != null && potentialLatestVersion.CompareTo(latestVersion) > 0)) + { + latestVersion = potentialLatestVersion; + } + } if (latestVersion == null) { diff --git a/eng/tools/RepoTasks/.editorconfig b/eng/tools/RepoTasks/.editorconfig new file mode 100644 index 000000000000..89bb5ad88f65 --- /dev/null +++ b/eng/tools/RepoTasks/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] +dotnet_diagnostic.CA1307.severity = none +dotnet_diagnostic.CA1308.severity = none +dotnet_diagnostic.CA1309.severity = none diff --git a/global.json b/global.json index 213d84ae5332..e00b9b5b4ac6 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "5.0.100-rc.2.20479.15" + "version": "6.0.100-alpha.1.20472.11" }, "tools": { - "dotnet": "5.0.100-rc.2.20479.15", + "dotnet": "6.0.100-alpha.1.20472.11", "runtimes": { "dotnet/x64": [ "2.1.18", diff --git a/src/Analyzers/Analyzers/test/AnalyzerTestBase.cs b/src/Analyzers/Analyzers/test/AnalyzerTestBase.cs index 2c324308c0c6..f70ac58c8b3f 100644 --- a/src/Analyzers/Analyzers/test/AnalyzerTestBase.cs +++ b/src/Analyzers/Analyzers/test/AnalyzerTestBase.cs @@ -13,7 +13,7 @@ public abstract class AnalyzerTestBase { public TestSource Read(string source) { - if (!source.EndsWith(".cs")) + if (!source.EndsWith(".cs", StringComparison.Ordinal)) { source = source + ".cs"; } @@ -30,7 +30,7 @@ public TestSource Read(string source) public Project CreateProject(string source) { - if (!source.EndsWith(".cs")) + if (!source.EndsWith(".cs", StringComparison.Ordinal)) { source = source + ".cs"; } diff --git a/src/Antiforgery/src/Internal/DefaultAntiforgery.cs b/src/Antiforgery/src/Internal/DefaultAntiforgery.cs index b310d2286b73..613adf73af9f 100644 --- a/src/Antiforgery/src/Internal/DefaultAntiforgery.cs +++ b/src/Antiforgery/src/Internal/DefaultAntiforgery.cs @@ -400,7 +400,7 @@ private void LogCacheHeaderOverrideWarning(HttpResponse response) var pragmaHeader = response.Headers[HeaderNames.Pragma]; if (!logWarning && !string.IsNullOrEmpty(pragmaHeader) - && string.Compare(pragmaHeader, "no-cache", ignoreCase: true) != 0) + && !string.Equals(pragmaHeader, "no-cache", StringComparison.OrdinalIgnoreCase)) { logWarning = true; } diff --git a/src/Components/Analyzers/src/ComponentParametersShouldBePublicCodeFixProvider.cs b/src/Components/Analyzers/src/ComponentParametersShouldBePublicCodeFixProvider.cs index 173633f0e9fd..0d89f0236d02 100644 --- a/src/Components/Analyzers/src/ComponentParametersShouldBePublicCodeFixProvider.cs +++ b/src/Components/Analyzers/src/ComponentParametersShouldBePublicCodeFixProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.Composition; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -37,7 +38,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType().First(); // Register a code action that will invoke the fix. - var title = Title.ToString(); + var title = Title.ToString(CultureInfo.InvariantCulture); context.RegisterCodeFix( CodeAction.Create( title: title, diff --git a/src/Components/Analyzers/test/AnalyzerTestBase.cs b/src/Components/Analyzers/test/AnalyzerTestBase.cs index 91bfe2d9cc41..5196831a1b84 100644 --- a/src/Components/Analyzers/test/AnalyzerTestBase.cs +++ b/src/Components/Analyzers/test/AnalyzerTestBase.cs @@ -16,7 +16,7 @@ public abstract class AnalyzerTestBase public TestSource Read(string source) { - if (!source.EndsWith(".cs")) + if (!source.EndsWith(".cs", StringComparison.Ordinal)) { source = source + ".cs"; } @@ -33,7 +33,7 @@ public TestSource Read(string source) public Project CreateProject(string source) { - if (!source.EndsWith(".cs")) + if (!source.EndsWith(".cs", StringComparison.Ordinal)) { source = source + ".cs"; } diff --git a/src/Components/Analyzers/test/Verifiers/CodeFixVerifier.cs b/src/Components/Analyzers/test/Verifiers/CodeFixVerifier.cs index cb6c9d432992..693b6ef8cef9 100644 --- a/src/Components/Analyzers/test/Verifiers/CodeFixVerifier.cs +++ b/src/Components/Analyzers/test/Verifiers/CodeFixVerifier.cs @@ -3,14 +3,15 @@ // Most of the code in this file comes from the default Roslyn Analyzer project template +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; -using System.Collections.Generic; -using System.Linq; -using System.Threading; using Xunit; namespace TestHelper @@ -82,7 +83,7 @@ private void VerifyFix(string language, DiagnosticAnalyzer analyzer, CodeFixProv var analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document }); var compilerDiagnostics = GetCompilerDiagnostics(document); var attempts = analyzerDiagnostics.Length; - + for (int i = 0; i < attempts; ++i) { var actions = new List(); @@ -113,7 +114,9 @@ private void VerifyFix(string language, DiagnosticAnalyzer analyzer, CodeFixProv newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document)); Assert.True(false, - string.Format("Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n", + string.Format( + CultureInfo.InvariantCulture, + "Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n", string.Join("\r\n", newCompilerDiagnostics.Select(d => d.ToString())), document.GetSyntaxRootAsync().Result.ToFullString())); } diff --git a/src/Components/Analyzers/test/Verifiers/DiagnosticVerifier.cs b/src/Components/Analyzers/test/Verifiers/DiagnosticVerifier.cs index f56d4ff93d74..aacb55afac3c 100644 --- a/src/Components/Analyzers/test/Verifiers/DiagnosticVerifier.cs +++ b/src/Components/Analyzers/test/Verifiers/DiagnosticVerifier.cs @@ -3,11 +3,13 @@ // Most of the code in this file comes from the default Roslyn Analyzer project template -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Diagnostics; +using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; using Xunit; namespace TestHelper @@ -82,7 +84,7 @@ protected void VerifyBasicDiagnostic(string[] sources, params DiagnosticResult[] } /// - /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run, + /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run, /// then verifies each of them. /// /// An array of strings to create source documents from to run the analyzers on @@ -115,7 +117,7 @@ private static void VerifyDiagnosticResults(IEnumerable actualResult string diagnosticsOutput = actualResults.Any() ? FormatDiagnostics(analyzer, actualResults.ToArray()) : " NONE."; Assert.True(false, - string.Format("Mismatch between number of diagnostics returned, expected \"{0}\" actual \"{1}\"\r\n\r\nDiagnostics:\r\n{2}\r\n", expectedCount, actualCount, diagnosticsOutput)); + string.Format(CultureInfo.InvariantCulture, "Mismatch between number of diagnostics returned, expected \"{0}\" actual \"{1}\"\r\n\r\nDiagnostics:\r\n{2}\r\n", expectedCount, actualCount, diagnosticsOutput)); } for (int i = 0; i < expectedResults.Length; i++) @@ -128,7 +130,7 @@ private static void VerifyDiagnosticResults(IEnumerable actualResult if (actual.Location != Location.None) { Assert.True(false, - string.Format("Expected:\nA project diagnostic with No location\nActual:\n{0}", + string.Format(CultureInfo.InvariantCulture, "Expected:\nA project diagnostic with No location\nActual:\n{0}", FormatDiagnostics(analyzer, actual))); } } @@ -140,7 +142,9 @@ private static void VerifyDiagnosticResults(IEnumerable actualResult if (additionalLocations.Length != expected.Locations.Length - 1) { Assert.True(false, - string.Format("Expected {0} additional locations but got {1} for Diagnostic:\r\n {2}\r\n", + string.Format( + CultureInfo.InvariantCulture, + "Expected {0} additional locations but got {1} for Diagnostic:\r\n {2}\r\n", expected.Locations.Length - 1, additionalLocations.Length, FormatDiagnostics(analyzer, actual))); } @@ -154,21 +158,27 @@ private static void VerifyDiagnosticResults(IEnumerable actualResult if (actual.Id != expected.Id) { Assert.True(false, - string.Format("Expected diagnostic id to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", + string.Format( + CultureInfo.InvariantCulture, + "Expected diagnostic id to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Id, actual.Id, FormatDiagnostics(analyzer, actual))); } if (actual.Severity != expected.Severity) { Assert.True(false, - string.Format("Expected diagnostic severity to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", + string.Format( + CultureInfo.InvariantCulture, + "Expected diagnostic severity to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Severity, actual.Severity, FormatDiagnostics(analyzer, actual))); } if (actual.GetMessage() != expected.Message) { Assert.True(false, - string.Format("Expected diagnostic message to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", + string.Format( + CultureInfo.InvariantCulture, + "Expected diagnostic message to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Message, actual.GetMessage(), FormatDiagnostics(analyzer, actual))); } } @@ -186,7 +196,9 @@ private static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagno var actualSpan = actual.GetLineSpan(); Assert.True(actualSpan.Path == expected.Path || (actualSpan.Path != null && actualSpan.Path.Contains("Test0.") && expected.Path.Contains("Test.")), - string.Format("Expected diagnostic to be in file \"{0}\" was actually in file \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", + string.Format( + CultureInfo.InvariantCulture, + "Expected diagnostic to be in file \"{0}\" was actually in file \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Path, actualSpan.Path, FormatDiagnostics(analyzer, diagnostic))); var actualLinePosition = actualSpan.StartLinePosition; @@ -197,7 +209,9 @@ private static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagno if (actualLinePosition.Line + 1 != expected.Line) { Assert.True(false, - string.Format("Expected diagnostic to be on line \"{0}\" was actually on line \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", + string.Format( + CultureInfo.InvariantCulture, + "Expected diagnostic to be on line \"{0}\" was actually on line \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Line, actualLinePosition.Line + 1, FormatDiagnostics(analyzer, diagnostic))); } } @@ -208,7 +222,9 @@ private static void VerifyDiagnosticLocation(DiagnosticAnalyzer analyzer, Diagno if (actualLinePosition.Character + 1 != expected.Column) { Assert.True(false, - string.Format("Expected diagnostic to start at column \"{0}\" was actually at column \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", + string.Format( + CultureInfo.InvariantCulture, + "Expected diagnostic to start at column \"{0}\" was actually at column \"{1}\"\r\n\r\nDiagnostic:\r\n {2}\r\n", expected.Column, actualLinePosition.Character + 1, FormatDiagnostics(analyzer, diagnostic))); } } @@ -239,17 +255,19 @@ private static string FormatDiagnostics(DiagnosticAnalyzer analyzer, params Diag var location = diagnostics[i].Location; if (location == Location.None) { - builder.AppendFormat("GetGlobalResult({0}.{1})", analyzerType.Name, rule.Id); + builder.AppendFormat(CultureInfo.InvariantCulture, "GetGlobalResult({0}.{1})", analyzerType.Name, rule.Id); } else { Assert.True(location.IsInSource, $"Test base does not currently handle diagnostics in metadata locations. Diagnostic in metadata: {diagnostics[i]}\r\n"); - string resultMethodName = diagnostics[i].Location.SourceTree.FilePath.EndsWith(".cs") ? "GetCSharpResultAt" : "GetBasicResultAt"; + string resultMethodName = diagnostics[i].Location.SourceTree.FilePath.EndsWith(".cs", StringComparison.Ordinal) ? "GetCSharpResultAt" : "GetBasicResultAt"; var linePosition = diagnostics[i].Location.GetLineSpan().StartLinePosition; - builder.AppendFormat("{0}({1}, {2}, {3}.{4})", + builder.AppendFormat( + CultureInfo.InvariantCulture, + "{0}({1}, {2}, {3}.{4})", resultMethodName, linePosition.Line + 1, linePosition.Character + 1, diff --git a/src/Components/Components/src/ComponentBase.cs b/src/Components/Components/src/ComponentBase.cs index dd80af0fd3bf..1780a78a6a84 100644 --- a/src/Components/Components/src/ComponentBase.cs +++ b/src/Components/Components/src/ComponentBase.cs @@ -17,8 +17,6 @@ namespace Microsoft.AspNetCore.Components // about IComponent). This gives us flexibility to change the lifecycle concepts easily, // or for developers to design their own lifecycles as different base classes. - // TODO: When the component lifecycle design stabilizes, add proper unit tests for ComponentBase. - /// /// Optional base class for components. Alternatively, components may /// implement directly. @@ -200,9 +198,8 @@ void IComponent.Attach(RenderHandle renderHandle) /// A that completes when the component has finished updating and rendering itself. /// /// - /// The method should be passed the entire set of parameter values each - /// time is called. It not required that the caller supply a parameter - /// value for all parameters that are logically understood by the component. + /// Parameters are passed when is called. It is not required that + /// the caller supply a parameter value for all of the parameters that are logically understood by the component. /// /// /// The default implementation of will set the value of each property diff --git a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj index 23f816726b13..a87f735c6fe1 100644 --- a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj +++ b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj @@ -28,7 +28,7 @@ - + diff --git a/src/Components/Components/src/Routing/TemplateSegment.cs b/src/Components/Components/src/Routing/TemplateSegment.cs index c4d351995199..e08953158484 100644 --- a/src/Components/Components/src/Routing/TemplateSegment.cs +++ b/src/Components/Components/src/Routing/TemplateSegment.cs @@ -61,7 +61,7 @@ public TemplateSegment(string template, string segment, bool isParameter) // Set the IsOptional flag to true if any type constraints // for this parameter are designated as optional. - IsOptional = tokens.Skip(1).Any(token => token.EndsWith("?")); + IsOptional = tokens.Skip(1).Any(token => token.EndsWith('?')); Value = tokens[0]; Constraints = tokens.Skip(1) diff --git a/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs b/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs index 8df50921127b..23889dd40d01 100644 --- a/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs +++ b/src/Components/Components/test/EventCallbackFactoryBinderExtensionsTest.cs @@ -396,7 +396,7 @@ public async Task CreateBinder_DateTime() var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(CultureInfo.InvariantCulture), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -415,7 +415,7 @@ public async Task CreateBinder_NullableDateTime() var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(CultureInfo.InvariantCulture), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -435,7 +435,7 @@ public async Task CreateBinder_DateTime_Format() var expectedValue = new DateTime(2018, 3, 4); // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format, CultureInfo.InvariantCulture), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -455,7 +455,7 @@ public async Task CreateBinder_NullableDateTime_Format() var expectedValue = new DateTime(2018, 3, 4); // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format, CultureInfo.InvariantCulture), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -474,7 +474,7 @@ public async Task CreateBinder_DateTimeOffset() var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(CultureInfo.InvariantCulture), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -493,7 +493,7 @@ public async Task CreateBinder_NullableDateTimeOffset() var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3); // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(CultureInfo.InvariantCulture), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -513,7 +513,7 @@ public async Task CreateBinder_DateTimeOffset_Format() var expectedValue = new DateTime(2018, 3, 4); // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format, CultureInfo.InvariantCulture), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); @@ -533,7 +533,7 @@ public async Task CreateBinder_NullableDateTimeOffset_Format() var expectedValue = new DateTime(2018, 3, 4); // Act - await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format), }); + await binder.InvokeAsync(new ChangeEventArgs() { Value = expectedValue.ToString(format, CultureInfo.InvariantCulture), }); Assert.Equal(expectedValue, value); Assert.Equal(1, component.Count); diff --git a/src/Components/Components/test/RendererTest.cs b/src/Components/Components/test/RendererTest.cs index efa3db89915d..5a5acc6e896d 100644 --- a/src/Components/Components/test/RendererTest.cs +++ b/src/Components/Components/test/RendererTest.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Runtime.ExceptionServices; using System.Threading; @@ -224,7 +225,7 @@ public async Task CanRenderAsyncTopLevelComponents() { Assert.Equal(RenderTreeEditType.StepOut, edit.Type); }); - AssertFrame.Text(update.ReferenceFrames[0], (5 - i).ToString()); + AssertFrame.Text(update.ReferenceFrames[0], (5 - i).ToString(CultureInfo.InvariantCulture)); } } diff --git a/src/Components/Components/test/Routing/RouteTableFactoryTests.cs b/src/Components/Components/test/Routing/RouteTableFactoryTests.cs index 3a4887fba090..3690e4e2821e 100644 --- a/src/Components/Components/test/Routing/RouteTableFactoryTests.cs +++ b/src/Components/Components/test/Routing/RouteTableFactoryTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Components.Routing; using Microsoft.Extensions.DependencyModel; @@ -630,7 +631,7 @@ public void DoesNotThrowIfStableSortComparesRouteWithItself() Assert.Equal(17, routeTable.Routes.Length); for (var i = 0; i < 17; i++) { - var templateText = "r" + i.ToString().PadLeft(2, '0'); + var templateText = "r" + i.ToString(CultureInfo.InvariantCulture).PadLeft(2, '0'); Assert.Equal(templateText, routeTable.Routes[i].Template.TemplateText); } } diff --git a/src/Components/Components/test/Routing/RouterTest.cs b/src/Components/Components/test/Routing/RouterTest.cs index 29da11476bf9..acf84fee4f83 100644 --- a/src/Components/Components/test/Routing/RouterTest.cs +++ b/src/Components/Components/test/Routing/RouterTest.cs @@ -62,7 +62,7 @@ public async Task CanceledFailedOnNavigateAsyncDoesNothing() Action OnNavigateAsync = async (NavigationContext args) => { onNavigateInvoked += 1; - if (args.Path.EndsWith("jan")) + if (args.Path.EndsWith("jan", StringComparison.Ordinal)) { await Task.Delay(Timeout.Infinite, args.CancellationToken); throw new Exception("This is an uncaught exception."); @@ -96,7 +96,7 @@ public async Task AlreadyCanceledOnNavigateAsyncDoesNothing() var triggerCancel = new TaskCompletionSource(); Action OnNavigateAsync = async (NavigationContext args) => { - if (args.Path.EndsWith("jan")) + if (args.Path.EndsWith("jan", StringComparison.Ordinal)) { var tcs = new TaskCompletionSource(); await triggerCancel.Task; @@ -152,7 +152,7 @@ public async Task RefreshesOnceOnCancelledOnNavigateAsync() // Arrange Action OnNavigateAsync = async (NavigationContext args) => { - if (args.Path.EndsWith("jan")) + if (args.Path.EndsWith("jan", StringComparison.Ordinal)) { await Task.Delay(Timeout.Infinite, args.CancellationToken); } diff --git a/src/Components/ComponentsNoDeps.slnf b/src/Components/ComponentsNoDeps.slnf index 0596b3bc64a1..f4c4daa62617 100644 --- a/src/Components/ComponentsNoDeps.slnf +++ b/src/Components/ComponentsNoDeps.slnf @@ -14,6 +14,7 @@ "src\\Components\\Ignitor\\src\\Ignitor.csproj", "src\\Components\\Ignitor\\test\\Ignitor.Test.csproj", "src\\Components\\Samples\\BlazorServerApp\\BlazorServerApp.csproj", + "src\\Components\\Samples\\IgnitorSample\\IgnitorSample.csproj", "src\\Components\\Server\\src\\Microsoft.AspNetCore.Components.Server.csproj", "src\\Components\\Server\\test\\Microsoft.AspNetCore.Components.Server.Tests.csproj", "src\\Components\\WebAssembly\\Authentication.Msal\\src\\Microsoft.Authentication.WebAssembly.Msal.csproj", @@ -48,4 +49,4 @@ "src\\Components\\test\\testassets\\TestServer\\Components.TestServer.csproj" ] } -} +} \ No newline at end of file diff --git a/src/Components/Ignitor/src/BlazorClient.cs b/src/Components/Ignitor/src/BlazorClient.cs index b19ab8b3dd5f..a06660e6b678 100644 --- a/src/Components/Ignitor/src/BlazorClient.cs +++ b/src/Components/Ignitor/src/BlazorClient.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.Linq; using System.Net.Http; using System.Text.Json; @@ -35,8 +36,10 @@ public BlazorClient() }); } - public TimeSpan? DefaultConnectionTimeout { get; set; } = TimeSpan.FromSeconds(20); - public TimeSpan? DefaultOperationTimeout { get; set; } = TimeSpan.FromMilliseconds(500); + public TimeSpan? DefaultConnectionTimeout { get; set; } = Debugger.IsAttached ? + Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(20); + public TimeSpan? DefaultOperationTimeout { get; set; } = Debugger.IsAttached ? + Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(500); /// /// Gets or sets a value that determines whether the client will capture data such @@ -475,7 +478,7 @@ private Uri GetHubUrl(Uri uri) else { var builder = new UriBuilder(uri); - builder.Path += builder.Path.EndsWith("/") ? "_blazor" : "/_blazor"; + builder.Path += builder.Path.EndsWith("/", StringComparison.Ordinal) ? "_blazor" : "/_blazor"; return builder.Uri; } } diff --git a/src/Components/Ignitor/src/ElementHive.cs b/src/Components/Ignitor/src/ElementHive.cs index b7819b427634..07e551c870bf 100644 --- a/src/Components/Ignitor/src/ElementHive.cs +++ b/src/Components/Ignitor/src/ElementHive.cs @@ -259,7 +259,7 @@ private int InsertFrame(RenderBatch batch, ContainerNode parent, int childIndex, case RenderTreeFrameType.Region: { - return InsertFrameRange(batch, parent, childIndex, frames, frameIndex + 1, frameIndex + CountDescendantFrames(frame)); + return InsertFrameRange(batch, parent, childIndex, frames, frameIndex + 1, frameIndex + frame.RegionSubtreeLength); } case RenderTreeFrameType.ElementReferenceCapture: @@ -322,7 +322,8 @@ private void InsertElement(RenderBatch batch, ContainerNode parent, int childInd { // Note: we don't handle SVG here var newElement = new ElementNode(frame.ElementName); - parent.InsertLogicalChild(newElement, childIndex); + + var inserted = false; // Apply attributes for (var i = frameIndex + 1; i < frameIndex + frame.ElementSubtreeLength; i++) @@ -334,12 +335,21 @@ private void InsertElement(RenderBatch batch, ContainerNode parent, int childInd } else { + parent.InsertLogicalChild(newElement, childIndex); + inserted = true; + // As soon as we see a non-attribute child, all the subsequent child frames are // not attributes, so bail out and insert the remnants recursively InsertFrameRange(batch, newElement, 0, frames, i, frameIndex + frame.ElementSubtreeLength); break; } } + + // this element did not have any children, so it's not inserted yet. + if (!inserted) + { + parent.InsertLogicalChild(newElement, childIndex); + } } private void ApplyAttribute(RenderBatch batch, ElementNode elementNode, RenderTreeFrame attributeFrame) diff --git a/src/Components/Ignitor/src/NodeSerializer.cs b/src/Components/Ignitor/src/NodeSerializer.cs index 814635f6d527..c405bdd394fd 100644 --- a/src/Components/Ignitor/src/NodeSerializer.cs +++ b/src/Components/Ignitor/src/NodeSerializer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; #nullable enable @@ -154,7 +155,7 @@ private void SerializeElement(ElementNode elementNode) Write(" "); Write(evt.Value.EventName); Write("("); - Write(evt.Value.EventId.ToString()); + Write(evt.Value.EventId.ToString(CultureInfo.InvariantCulture)); Write(")"); } Write("]"); @@ -181,7 +182,7 @@ private void SerializeChildren(ContainerNode containerNode) private void SerializeComponent(ComponentNode component) { Write("[Component ( "); - Write(component.ComponentId.ToString()); + Write(component.ComponentId.ToString(CultureInfo.InvariantCulture)); WriteLine(" )]"); _depth++; SerializeChildren(component); diff --git a/src/Components/Ignitor/test/RenderBatchReaderTest.cs b/src/Components/Ignitor/test/RenderBatchReaderTest.cs index 7a703be6c6fd..917da8a8acbd 100644 --- a/src/Components/Ignitor/test/RenderBatchReaderTest.cs +++ b/src/Components/Ignitor/test/RenderBatchReaderTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using Xunit; @@ -263,7 +264,7 @@ static void AssertBinaryContents(Span data, int startIndex, params object[ { // Assume enums are represented as ints var expectedEntry = expectedEntryIterationVar.GetType().IsEnum - ? Convert.ToInt32(expectedEntryIterationVar) + ? Convert.ToInt32(expectedEntryIterationVar, CultureInfo.InvariantCulture) : expectedEntryIterationVar; if (expectedEntry is int expectedInt) diff --git a/src/Components/Samples/BlazorServerApp/Pages/Counter.razor b/src/Components/Samples/BlazorServerApp/Pages/Counter.razor index 59c0d242c3aa..946512d45a7e 100644 --- a/src/Components/Samples/BlazorServerApp/Pages/Counter.razor +++ b/src/Components/Samples/BlazorServerApp/Pages/Counter.razor @@ -2,7 +2,7 @@

Counter

-

Current count: @currentCount

+

Current count: @currentCount

diff --git a/src/Components/Samples/IgnitorSample/IgnitorSample.csproj b/src/Components/Samples/IgnitorSample/IgnitorSample.csproj new file mode 100644 index 000000000000..36c8c55e4153 --- /dev/null +++ b/src/Components/Samples/IgnitorSample/IgnitorSample.csproj @@ -0,0 +1,14 @@ + + + + $(DefaultNetCoreTargetFramework) + false + enable + Exe + + + + + + + diff --git a/src/Components/Samples/IgnitorSample/Program.cs b/src/Components/Samples/IgnitorSample/Program.cs new file mode 100644 index 000000000000..e272dc5b8787 --- /dev/null +++ b/src/Components/Samples/IgnitorSample/Program.cs @@ -0,0 +1,45 @@ +using System; +using System.Diagnostics; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Ignitor; +using Microsoft.AspNetCore.SignalR.Client; + +namespace IgnitorSample +{ + /// + /// This is a minimal sample that lets you try out Ignitor against a Blazor Server app. + /// To use this, first launch the server app. Update the code below to point to the host url and run the test. + /// + class Program + { + private static readonly string ServerUrl = "https://localhost:5001"; + private static readonly JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web); + + static async Task Main(string[] args) + { + var client = new BlazorClient(); + await client.ConnectAsync(new Uri(ServerUrl)); + + await VerifyNavigationAsync(client); + + Console.WriteLine("Done"); + } + + static async ValueTask VerifyNavigationAsync(BlazorClient client) + { + await client.ExpectRenderBatch(() => client.NavigateAsync($"{ServerUrl}/counter")); + client.Hive.TryFindElementById("counter", out var counter); + Debug.Assert(counter != null, "We must have navigated to counter."); + } + } + + static class BlazorClientExtensions + { + public static Task NavigateAsync(this BlazorClient client, string url, CancellationToken cancellationToken = default) + { + return client.HubConnection.InvokeAsync("OnLocationChanged", url, false, cancellationToken); + } + } +} diff --git a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs index eec26e87adcb..776d2521561c 100644 --- a/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs +++ b/src/Components/Server/src/Builder/ComponentEndpointRouteBuilderExtensions.cs @@ -105,7 +105,7 @@ public static ComponentEndpointConventionBuilder MapBlazorHub( var hubEndpoint = endpoints.MapHub(path, configureOptions); var disconnectEndpoint = endpoints.Map( - (path.EndsWith("/") ? path : path + "/") + "disconnect/", + (path.EndsWith('/') ? path : path + "/") + "disconnect/", endpoints.CreateApplicationBuilder().UseMiddleware().Build()) .WithDisplayName("Blazor disconnect"); diff --git a/src/Components/Server/src/Circuits/CircuitHost.cs b/src/Components/Server/src/Circuits/CircuitHost.cs index f3b34f4f5758..91222e9513cd 100644 --- a/src/Components/Server/src/Circuits/CircuitHost.cs +++ b/src/Components/Server/src/Circuits/CircuitHost.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; @@ -112,7 +113,7 @@ public Task InitializeAsync(CancellationToken cancellationToken) for (var i = 0; i < count; i++) { var (componentType, parameters, sequence) = Descriptors[i]; - await Renderer.AddComponentAsync(componentType, parameters, sequence.ToString()); + await Renderer.AddComponentAsync(componentType, parameters, sequence.ToString(CultureInfo.InvariantCulture)); } Log.InitializationSucceeded(_logger); @@ -423,7 +424,7 @@ await Renderer.Dispatcher.InvokeAsync(() => { // A failure in dispatching an event means that it was an attempt to use an invalid event id. // A well-behaved client won't do this. - Log.DispatchEventFailedToDispatchEvent(_logger, webEventData.EventHandlerId.ToString(), ex); + Log.DispatchEventFailedToDispatchEvent(_logger, webEventData.EventHandlerId.ToString(CultureInfo.InvariantCulture), ex); await TryNotifyClientErrorAsync(Client, GetClientErrorMessage(ex, "Failed to dispatch event.")); UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, isTerminating: false)); } diff --git a/src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs b/src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs index ac7be325234c..94c03ea58516 100644 --- a/src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs +++ b/src/Components/Server/src/Circuits/CircuitOptionsJSInteropDetailedErrorsConfiguration.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; @@ -18,7 +19,9 @@ public CircuitOptionsJSInteropDetailedErrorsConfiguration(IConfiguration configu public void Configure(CircuitOptions options) { - options.DetailedErrors = Configuration.GetValue(WebHostDefaults.DetailedErrorsKey); + var value = Configuration[WebHostDefaults.DetailedErrorsKey]; + options.DetailedErrors = string.Equals(value, "true", StringComparison.OrdinalIgnoreCase) || + string.Equals(value, "1", StringComparison.OrdinalIgnoreCase); } } } diff --git a/src/Components/Server/src/ComponentHub.cs b/src/Components/Server/src/ComponentHub.cs index 779b4b005341..389a97ab0341 100644 --- a/src/Components/Server/src/ComponentHub.cs +++ b/src/Components/Server/src/ComponentHub.cs @@ -89,8 +89,8 @@ public async ValueTask StartCircuit(string baseUri, string uri, string s if (baseUri == null || uri == null || - !Uri.IsWellFormedUriString(baseUri, UriKind.Absolute) || - !Uri.IsWellFormedUriString(uri, UriKind.Absolute)) + !Uri.TryCreate(baseUri, UriKind.Absolute, out _) || + !Uri.TryCreate(uri, UriKind.Absolute, out _)) { // We do some really minimal validation here to prevent obviously wrong data from getting in // without duplicating too much logic. diff --git a/src/Components/Server/test/Circuits/RenderBatchWriterTest.cs b/src/Components/Server/test/Circuits/RenderBatchWriterTest.cs index b52862bb2dc1..7fdf9231676e 100644 --- a/src/Components/Server/test/Circuits/RenderBatchWriterTest.cs +++ b/src/Components/Server/test/Circuits/RenderBatchWriterTest.cs @@ -1,6 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; +using System.Threading.Tasks; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.RenderTree; @@ -8,11 +14,6 @@ using Microsoft.AspNetCore.Components.Web.Rendering; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading.Tasks; using Xunit; namespace Microsoft.AspNetCore.Components.Server @@ -314,7 +315,7 @@ static void AssertBinaryContents(Span data, int startIndex, params object[ { // Assume enums are represented as ints var expectedEntry = expectedEntryIterationVar.GetType().IsEnum - ? Convert.ToInt32(expectedEntryIterationVar) + ? Convert.ToInt32(expectedEntryIterationVar, CultureInfo.InvariantCulture) : expectedEntryIterationVar; if (expectedEntry is int expectedInt) diff --git a/src/Components/Web.JS/.gitignore b/src/Components/Web.JS/.gitignore index 10999e07926c..b1e47fe5bdee 100644 --- a/src/Components/Web.JS/.gitignore +++ b/src/Components/Web.JS/.gitignore @@ -1,2 +1,3 @@ node_modules/ dist/Debug/ +dist/Release/blazor.webassembly.js diff --git a/src/Components/Web/src/Forms/InputBase.cs b/src/Components/Web/src/Forms/InputBase.cs index cd0c790457d8..92eb780c8cdd 100644 --- a/src/Components/Web/src/Forms/InputBase.cs +++ b/src/Components/Web/src/Forms/InputBase.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; @@ -175,7 +176,7 @@ protected string CssClass { if (AdditionalAttributes != null && AdditionalAttributes.TryGetValue("class", out var @class) && - !string.IsNullOrEmpty(Convert.ToString(@class))) + !string.IsNullOrEmpty(Convert.ToString(@class, CultureInfo.InvariantCulture))) { return $"{@class} {FieldClass}"; } diff --git a/src/Components/Web/src/Forms/InputDate.cs b/src/Components/Web/src/Forms/InputDate.cs index 9b180f76e25e..8ab564977f0c 100644 --- a/src/Components/Web/src/Forms/InputDate.cs +++ b/src/Components/Web/src/Forms/InputDate.cs @@ -77,7 +77,7 @@ protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(fa } else { - validationErrorMessage = string.Format(ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName); + validationErrorMessage = string.Format(CultureInfo.InvariantCulture, ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName); return false; } } diff --git a/src/Components/Web/src/Forms/InputNumber.cs b/src/Components/Web/src/Forms/InputNumber.cs index 7c51654a855e..ed7593583008 100644 --- a/src/Components/Web/src/Forms/InputNumber.cs +++ b/src/Components/Web/src/Forms/InputNumber.cs @@ -64,7 +64,7 @@ protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(fa } else { - validationErrorMessage = string.Format(ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName); + validationErrorMessage = string.Format(CultureInfo.InvariantCulture, ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName); return false; } } diff --git a/src/Components/Web/src/Forms/InputRadio.cs b/src/Components/Web/src/Forms/InputRadio.cs index 77df88376f08..f9091866ae3a 100644 --- a/src/Components/Web/src/Forms/InputRadio.cs +++ b/src/Components/Web/src/Forms/InputRadio.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using Microsoft.AspNetCore.Components.Rendering; namespace Microsoft.AspNetCore.Components.Forms @@ -41,7 +42,7 @@ private string GetCssClass(string fieldClass) { if (AdditionalAttributes != null && AdditionalAttributes.TryGetValue("class", out var @class) && - !string.IsNullOrEmpty(Convert.ToString(@class))) + !string.IsNullOrEmpty(Convert.ToString(@class, CultureInfo.InvariantCulture))) { return $"{@class} {fieldClass}"; } diff --git a/src/Components/Web/src/Routing/NavLink.cs b/src/Components/Web/src/Routing/NavLink.cs index 05f831a89b9b..27a73318cf9c 100644 --- a/src/Components/Web/src/Routing/NavLink.cs +++ b/src/Components/Web/src/Routing/NavLink.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Diagnostics; using Microsoft.AspNetCore.Components.Rendering; @@ -67,7 +68,7 @@ protected override void OnParametersSet() var href = (string?)null; if (AdditionalAttributes != null && AdditionalAttributes.TryGetValue("href", out var obj)) { - href = Convert.ToString(obj); + href = Convert.ToString(obj, CultureInfo.InvariantCulture); } _hrefAbsolute = href == null ? null : NavigationManger.ToAbsoluteUri(href).AbsoluteUri; @@ -76,7 +77,7 @@ protected override void OnParametersSet() _class = (string?)null; if (AdditionalAttributes != null && AdditionalAttributes.TryGetValue("class", out obj)) { - _class = Convert.ToString(obj); + _class = Convert.ToString(obj, CultureInfo.InvariantCulture); } UpdateCssClass(); diff --git a/src/Components/Web/test/Forms/InputBaseTest.cs b/src/Components/Web/test/Forms/InputBaseTest.cs index 6a8da5ca7666..3542a5b24403 100644 --- a/src/Components/Web/test/Forms/InputBaseTest.cs +++ b/src/Components/Web/test/Forms/InputBaseTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Test.Helpers; @@ -515,7 +516,7 @@ public async Task SetCurrentValueAsStringAsync(string value) private class TestDateInputComponent : TestInputComponent { protected override string FormatValueAsString(DateTime value) - => value.ToString("yyyy/MM/dd"); + => value.ToString("yyyy/MM/dd", CultureInfo.InvariantCulture); protected override bool TryParseValueFromString(string value, out DateTime result, out string validationErrorMessage) { diff --git a/src/Components/WebAssembly/DevServer/src/Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj b/src/Components/WebAssembly/DevServer/src/Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj index 200328464682..4a57cc7f0bb0 100644 --- a/src/Components/WebAssembly/DevServer/src/Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj +++ b/src/Components/WebAssembly/DevServer/src/Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj @@ -12,24 +12,10 @@ $(NoWarn.Replace('1591', '')) false - - - true - true - - - - + @@ -46,5 +32,4 @@ - diff --git a/src/Components/WebAssembly/Sdk/integrationtests/ServiceWorkerAssert.cs b/src/Components/WebAssembly/Sdk/integrationtests/ServiceWorkerAssert.cs index a107f6bd66a7..b35dcf7dd08a 100644 --- a/src/Components/WebAssembly/Sdk/integrationtests/ServiceWorkerAssert.cs +++ b/src/Components/WebAssembly/Sdk/integrationtests/ServiceWorkerAssert.cs @@ -71,8 +71,8 @@ private static bool IsCompressedFile(string path) private static AssetsManifestFile ReadServiceWorkerAssetsManifest(string assetsManifestResolvedPath) { var jsContents = File.ReadAllText(assetsManifestResolvedPath); - var jsonStart = jsContents.IndexOf("{"); - var jsonLength = jsContents.LastIndexOf("}") - jsonStart + 1; + var jsonStart = jsContents.IndexOf('{'); + var jsonLength = jsContents.LastIndexOf('}') - jsonStart + 1; var json = jsContents.Substring(jsonStart, jsonLength); return JsonSerializer.Deserialize(json); } diff --git a/src/Components/WebAssembly/Sdk/integrationtests/WasmBuildLazyLoadTest.cs b/src/Components/WebAssembly/Sdk/integrationtests/WasmBuildLazyLoadTest.cs index 88a7fb842d9a..ed5572fb2ec5 100644 --- a/src/Components/WebAssembly/Sdk/integrationtests/WasmBuildLazyLoadTest.cs +++ b/src/Components/WebAssembly/Sdk/integrationtests/WasmBuildLazyLoadTest.cs @@ -165,6 +165,48 @@ public async Task Publish_LazyLoadExplicitAssembly_Release_Works() Assert.Contains("blazorwasm.dll", assemblies.Keys); } + [Fact] + public async Task Build_LazyLoadExplicitAssembly_InvalidAssembly() + { + // Arrange + using var project = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" }); + project.Configuration = "Release"; + + project.AddProjectFileContent( +@" + + + +"); + // Act + var result = await MSBuildProcessManager.DotnetMSBuild(project); + + // Assert + Assert.BuildError(result, "BLAZORSDK1001"); + Assert.BuildFailed(result); + } + + [Fact] + public async Task Publish_LazyLoadExplicitAssembly_InvalidAssembly() + { + // Arrange + using var project = ProjectDirectory.Create("blazorwasm", additionalProjects: new[] { "razorclasslibrary" }); + project.Configuration = "Release"; + + project.AddProjectFileContent( +@" + + + +"); + // Act + var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish"); + + // Assert + Assert.BuildError(result, "BLAZORSDK1001"); + Assert.BuildFailed(result); + } + private static BootJsonData ReadBootJsonData(MSBuildResult result, string path) { return JsonSerializer.Deserialize( diff --git a/src/Components/WebAssembly/Sdk/src/targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets b/src/Components/WebAssembly/Sdk/src/targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets index 0f9a3d9c2b55..66ac6e99d989 100644 --- a/src/Components/WebAssembly/Sdk/src/targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets +++ b/src/Components/WebAssembly/Sdk/src/targets/Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets @@ -284,9 +284,15 @@ Copyright (c) .NET Foundation. All rights reserved. <_BlazorBuildBootJsonPath>$(IntermediateOutputPath)blazor.boot.json + <_BlazorOutputContent>@(_BlazorOutputWithHash) <_BlazorWebAssemblyLoadAllGlobalizationData Condition="'$(BlazorWebAssemblyLoadAllGlobalizationData)' == ''">false + + + + <_BlazorOutputContent>@(_BlazorPublishBootResourceWithHash) + + + + false - net5.0 - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, 'AspNetCore.sln'))\ $(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\build\netstandard2.0\Sdk.Razor.CurrentVersion.props diff --git a/src/Components/WebAssembly/Server/src/DebugProxyLauncher.cs b/src/Components/WebAssembly/Server/src/DebugProxyLauncher.cs index 58f6b260251b..53db2fb5e344 100644 --- a/src/Components/WebAssembly/Server/src/DebugProxyLauncher.cs +++ b/src/Components/WebAssembly/Server/src/DebugProxyLauncher.cs @@ -77,7 +77,7 @@ private static void RemoveUnwantedEnvironmentVariables(IDictionary key.StartsWith("ASPNETCORE_")).ToList(); + var keysToRemove = environment.Keys.Where(key => key.StartsWith("ASPNETCORE_", StringComparison.Ordinal)).ToList(); foreach (var key in keysToRemove) { environment.Remove(key); diff --git a/src/Components/WebAssembly/Server/src/TargetPickerUi.cs b/src/Components/WebAssembly/Server/src/TargetPickerUi.cs index fda22452d27f..5ce4d4ea2ea5 100644 --- a/src/Components/WebAssembly/Server/src/TargetPickerUi.cs +++ b/src/Components/WebAssembly/Server/src/TargetPickerUi.cs @@ -9,6 +9,7 @@ using System.Net.Http; using System.Runtime.InteropServices; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -23,7 +24,7 @@ public class TargetPickerUi { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true, - IgnoreNullValues = true + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; private string _browserHost; diff --git a/src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs b/src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs index 30763ce44aca..f285301e9e6a 100644 --- a/src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs +++ b/src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs @@ -339,7 +339,7 @@ private string GetReturnUrl(TAuthenticationState state, string defaultReturnUrl } var fromQuery = QueryStringHelper.GetParameter(new Uri(Navigation.Uri).Query, "returnUrl"); - if (!string.IsNullOrWhiteSpace(fromQuery) && !fromQuery.StartsWith(Navigation.BaseUri)) + if (!string.IsNullOrWhiteSpace(fromQuery) && !fromQuery.StartsWith(Navigation.BaseUri, StringComparison.Ordinal)) { // This is an extra check to prevent open redirects. throw new InvalidOperationException("Invalid return url. The return url needs to have the same origin as the current page."); diff --git a/src/Components/WebAssembly/WebAssembly.Authentication/test/WebAssemblyAuthenticationServiceCollectionExtensionsTests.cs b/src/Components/WebAssembly/WebAssembly.Authentication/test/WebAssemblyAuthenticationServiceCollectionExtensionsTests.cs index d9996a124d7f..e05a55b76c02 100644 --- a/src/Components/WebAssembly/WebAssembly.Authentication/test/WebAssemblyAuthenticationServiceCollectionExtensionsTests.cs +++ b/src/Components/WebAssembly/WebAssembly.Authentication/test/WebAssemblyAuthenticationServiceCollectionExtensionsTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Routing; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; @@ -366,7 +367,7 @@ public void AddOidc_CustomState_SetsUpConfiguration() var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker()); var calls = 0; - builder.Services.AddOidcAuthentication(options => options.ProviderOptions.Authority = (++calls).ToString()); + builder.Services.AddOidcAuthentication(options => options.ProviderOptions.Authority = (++calls).ToString(CultureInfo.InvariantCulture)); builder.Services.Replace(ServiceDescriptor.Singleton(typeof(NavigationManager), new TestNavigationManager())); var host = builder.Build(); @@ -388,7 +389,7 @@ public void AddOidc_CustomStateAndAccount_SetsUpConfiguration() var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker()); var calls = 0; - builder.Services.AddOidcAuthentication(options => options.ProviderOptions.Authority = (++calls).ToString()); + builder.Services.AddOidcAuthentication(options => options.ProviderOptions.Authority = (++calls).ToString(CultureInfo.InvariantCulture)); builder.Services.Replace(ServiceDescriptor.Singleton(typeof(NavigationManager), new TestNavigationManager())); var host = builder.Build(); diff --git a/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs b/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs index 9e6215c70a75..8861ece33e8d 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.IO; using System.Linq; using Microsoft.AspNetCore.Components.Routing; @@ -86,7 +87,7 @@ private void InitializeRegisteredRootComponents(WebAssemblyJSRuntimeInvoker jsRu var typeName = jsRuntimeInvoker.InvokeUnmarshalled(RegisteredComponentsInterop.GetTypeName, id, null, null); var serializedParameterDefinitions = jsRuntimeInvoker.InvokeUnmarshalled(RegisteredComponentsInterop.GetParameterDefinitions, id, null, null); var serializedParameterValues = jsRuntimeInvoker.InvokeUnmarshalled(RegisteredComponentsInterop.GetParameterValues, id, null, null); - registeredComponents[i] = new WebAssemblyComponentMarker(WebAssemblyComponentMarker.ClientMarkerType, assembly, typeName, serializedParameterDefinitions, serializedParameterValues, id.ToString()); + registeredComponents[i] = new WebAssemblyComponentMarker(WebAssemblyComponentMarker.ClientMarkerType, assembly, typeName, serializedParameterDefinitions, serializedParameterValues, id.ToString(CultureInfo.InvariantCulture)); } var componentDeserializer = WebAssemblyComponentParameterDeserializer.Instance; diff --git a/src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs b/src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs index a9820985ebc6..6ae0c7a02d2f 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Microsoft.JSInterop.Infrastructure; using Microsoft.JSInterop.WebAssembly; @@ -21,7 +22,7 @@ private DefaultWebAssemblyJSRuntime() #pragma warning disable IDE0051 // Remove unused private members. Invoked via Mono's JS interop mechanism (invoke_method) private static string InvokeDotNet(string assemblyName, string methodIdentifier, string dotNetObjectId, string argsJson) { - var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId == null ? default : long.Parse(dotNetObjectId), callId: null); + var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId == null ? default : long.Parse(dotNetObjectId, CultureInfo.InvariantCulture), callId: null); return DotNetDispatcher.Invoke(Instance, callInfo, argsJson); } @@ -39,7 +40,7 @@ private static void BeginInvokeDotNet(string callId, string assemblyNameOrDotNet long dotNetObjectId; if (char.IsDigit(assemblyNameOrDotNetObjectId[0])) { - dotNetObjectId = long.Parse(assemblyNameOrDotNetObjectId); + dotNetObjectId = long.Parse(assemblyNameOrDotNetObjectId, CultureInfo.InvariantCulture); assemblyName = null; } else diff --git a/src/Components/WebAssembly/WebAssembly/test/Hosting/WebAssemblyHostConfigurationTest.cs b/src/Components/WebAssembly/WebAssembly/test/Hosting/WebAssemblyHostConfigurationTest.cs index 922293fa0a3a..ac1550db3616 100644 --- a/src/Components/WebAssembly/WebAssembly/test/Hosting/WebAssemblyHostConfigurationTest.cs +++ b/src/Components/WebAssembly/WebAssembly/test/Hosting/WebAssemblyHostConfigurationTest.cs @@ -211,7 +211,7 @@ public void NewConfigurationProviderOverridesOldOneWhenKeyIsDuplicated() private class CustomizedTestConfigurationProvider : ConfigurationProvider { public CustomizedTestConfigurationProvider(string key, string value) - => Data.Add(key, value.ToUpper()); + => Data.Add(key, value.ToUpperInvariant()); public override void Set(string key, string value) { diff --git a/src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs b/src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs index 66b236ddf8ed..7bf7c69171aa 100644 --- a/src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs +++ b/src/Components/WebAssembly/testassets/HostedInAspNet.Server/Startup.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; @@ -26,7 +27,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, BootReso // and that it was possible to override the loading mechanism if (context.Request.Query.ContainsKey("customizedbootresource") || context.Request.Headers.ContainsKey("customizedbootresource") - || context.Request.Path.Value.EndsWith("/blazor.boot.json")) + || context.Request.Path.Value.EndsWith("/blazor.boot.json", StringComparison.Ordinal)) { bootResourceRequestLog.AddRequest(context.Request); } diff --git a/src/Components/benchmarkapps/Wasm.Performance/ConsoleHost/Scenarios/ComponentRenderingScenarioBase.cs b/src/Components/benchmarkapps/Wasm.Performance/ConsoleHost/Scenarios/ComponentRenderingScenarioBase.cs index bf5cbc5d833c..55705c91c2bd 100644 --- a/src/Components/benchmarkapps/Wasm.Performance/ConsoleHost/Scenarios/ComponentRenderingScenarioBase.cs +++ b/src/Components/benchmarkapps/Wasm.Performance/ConsoleHost/Scenarios/ComponentRenderingScenarioBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Threading.Tasks; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.DependencyInjection; @@ -20,7 +21,7 @@ protected ComponentRenderingScenarioBase(string name) OnExecute(() => { - var numCycles = cyclesOption.HasValue() ? int.Parse(cyclesOption.Value()) : 1; + var numCycles = cyclesOption.HasValue() ? int.Parse(cyclesOption.Value(), CultureInfo.InvariantCulture) : 1; var serviceCollection = new ServiceCollection(); PopulateServiceCollection(serviceCollection); diff --git a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs index 1b1ed2a70286..57234090223f 100644 --- a/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs +++ b/src/Components/test/E2ETest/Infrastructure/ServerFixtures/ServerFixture.cs @@ -41,7 +41,7 @@ public ServerFixture() private static Dictionary FindProjects() { return typeof(ServerFixture).Assembly.GetCustomAttributes() - .Where(m => m.Key.StartsWith("TestAssemblyApplication[")) + .Where(m => m.Key.StartsWith("TestAssemblyApplication[", StringComparison.Ordinal)) .ToDictionary(m => m.Key.Replace("TestAssemblyApplication", "").TrimStart('[').TrimEnd(']'), m => m.Value); diff --git a/src/Components/test/E2ETest/Infrastructure/WebDriverExtensions/BasicTestAppAuthenticationWebDriverExtensions.cs b/src/Components/test/E2ETest/Infrastructure/WebDriverExtensions/BasicTestAppAuthenticationWebDriverExtensions.cs index 8fec725d9b90..938e8508d1db 100644 --- a/src/Components/test/E2ETest/Infrastructure/WebDriverExtensions/BasicTestAppAuthenticationWebDriverExtensions.cs +++ b/src/Components/test/E2ETest/Infrastructure/WebDriverExtensions/BasicTestAppAuthenticationWebDriverExtensions.cs @@ -9,7 +9,7 @@ internal static class BasicTestAppAuthenticationWebDriverExtensions { public static void SignInAs(this IWebDriver browser, Uri baseUri, string usernameOrNull, string rolesOrNull, bool useSeparateTab = false) { - var basePath = baseUri.LocalPath.EndsWith("/") ? baseUri.LocalPath : baseUri.LocalPath + "/"; + var basePath = baseUri.LocalPath.EndsWith("/", StringComparison.Ordinal) ? baseUri.LocalPath : baseUri.LocalPath + "/"; var authenticationPageUrl = $"{basePath}Authentication"; var baseRelativeUri = usernameOrNull == null ? $"{authenticationPageUrl}?signout=true" diff --git a/src/Components/test/E2ETest/ServerExecutionTests/ServerGlobalizationTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/ServerGlobalizationTest.cs index 53f7a0c80526..0dae5ec04342 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/ServerGlobalizationTest.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/ServerGlobalizationTest.cs @@ -34,7 +34,6 @@ protected override void InitializeAsyncCore() Browser.Exists(By.Id("culture-selector")); } - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/24692")] [Theory] [InlineData("en-US")] [InlineData("fr-FR")] diff --git a/src/Components/test/E2ETest/Tests/BindTest.cs b/src/Components/test/E2ETest/Tests/BindTest.cs index ea5a0265d035..f6f21b199c54 100644 --- a/src/Components/test/E2ETest/Tests/BindTest.cs +++ b/src/Components/test/E2ETest/Tests/BindTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Text.Json; using BasicTestApp; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; @@ -389,7 +390,6 @@ public void CanBindTextboxShort() } [Fact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23826")] public void CanBindTextboxNullableShort() { var target = Browser.Exists(By.Id("textbox-nullable-short")); @@ -512,7 +512,6 @@ public void CanBindTextboxDouble() } [Fact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")] public void CanBindTextboxNullableDouble() { var target = Browser.Exists(By.Id("textbox-nullable-double")); @@ -612,7 +611,6 @@ public void CanBindTextboxNullableDecimal() // This tests what happens you put invalid (unconvertable) input in. This is separate from the // other tests because it requires type="text" - the other tests use type="number" [Fact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/24756")] public void CanBindTextbox_Decimal_InvalidInput() { var target = Browser.Exists(By.Id("textbox-decimal-invalid")); @@ -731,23 +729,23 @@ public void CanBindTextboxDateTime() var boundValue = Browser.Exists(By.Id("textbox-datetime-value")); var mirrorValue = Browser.Exists(By.Id("textbox-datetime-mirror")); var expected = new DateTime(1985, 3, 4); - Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Clear textbox; value updates to 01/01/0001 because that's the default target.Clear(); expected = default; - Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01/02/2000 00:00:00\t"); expected = new DateTime(2000, 1, 2); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -770,8 +768,8 @@ public void CanBindTextboxNullableDateTime() // Modify target; verify value is updated and that textboxes linked to the same data are updated var expected = new DateTime(2000, 1, 2); target.SendKeys("01/02/2000 00:00:00\t"); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); @@ -789,23 +787,23 @@ public void CanBindTextboxDateTimeOffset() var boundValue = Browser.Exists(By.Id("textbox-datetimeoffset-value")); var mirrorValue = Browser.Exists(By.Id("textbox-datetimeoffset-mirror")); var expected = new DateTimeOffset(new DateTime(1985, 3, 4), TimeSpan.FromHours(8)); - Assert.Equal(expected, DateTimeOffset.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); - Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTimeOffset.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Clear textbox; value updates to 01/01/0001 because that's the default target.Clear(); expected = default; - Browser.Equal(expected, () => DateTimeOffset.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); - Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTimeOffset.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01/02/2000 00:00:00 +08:00\t"); expected = new DateTimeOffset(new DateTime(2000, 1, 2), TimeSpan.FromHours(8)); - Browser.Equal(expected, () => DateTimeOffset.Parse(boundValue.Text)); - Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -828,8 +826,8 @@ public void CanBindTextboxNullableDateTimeOffset() // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("01/02/2000 00:00:00 +08:00" + "\t"); var expected = new DateTimeOffset(new DateTime(2000, 1, 2), TimeSpan.FromHours(8)); - Browser.Equal(expected, () => DateTimeOffset.Parse(boundValue.Text)); - Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); @@ -848,23 +846,23 @@ public void CanBindTextboxDateTimeWithFormat() var mirrorValue = Browser.Exists(By.Id("textbox-datetime-format-mirror")); var expected = new DateTime(1985, 3, 4); Assert.Equal("03-04", target.GetAttribute("value")); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Clear textbox; value updates to the default target.Clear(); target.SendKeys("\t"); expected = default; Browser.Equal("01-01", () => target.GetAttribute("value")); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01-02\t"); expected = new DateTime(DateTime.Now.Year, 1, 2); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -887,8 +885,8 @@ public void CanBindTextboxNullableDateTimeWithFormat() // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("01-02\t"); var expected = new DateTime(DateTime.Now.Year, 1, 2); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); @@ -907,22 +905,22 @@ public void CanBindTextboxDateTimeOffsetWithFormat() var mirrorValue = Browser.Exists(By.Id("textbox-datetimeoffset-format-mirror")); var expected = new DateTimeOffset(new DateTime(1985, 3, 4), TimeSpan.FromHours(8)); Assert.Equal("03-04", target.GetAttribute("value")); - Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); - Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Clear textbox; value updates to the default target.Clear(); expected = default; Browser.Equal("01-01", () => target.GetAttribute("value")); - Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); - Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01-02\t"); expected = new DateTimeOffset(new DateTime(DateTime.Now.Year, 1, 2), TimeSpan.FromHours(0)); - Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); + Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -948,8 +946,8 @@ public void CanBindTextboxNullableDateTimeOffsetWithFormat() // Modify target; verify value is updated and that textboxes linked to the same data are updated target.SendKeys("01-02" + "\t"); var expected = new DateTimeOffset(new DateTime(DateTime.Now.Year, 1, 2), TimeSpan.FromHours(0)); - Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); + Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); @@ -973,8 +971,8 @@ public void CanBindTextboxNullableDateTime_InvalidValue() // Modify target; verify value is updated and that textboxes linked to the same data are updated var expected = new DateTime(2000, 1, 2); target.SendKeys("01/02/2000 00:00:00\t"); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target to something invalid - the invalid change is reverted // back to the last valid value @@ -982,16 +980,16 @@ public void CanBindTextboxNullableDateTime_InvalidValue() target.SendKeys("05/06X"); Browser.Equal("05/06X", () => target.GetAttribute("value")); target.SendKeys("\t"); - Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Now change it to something valid target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05/06\t"); expected = new DateTime(DateTime.Now.Year, 5, 6); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -1003,16 +1001,16 @@ public void CanBindTextboxDateTimeOffset_InvalidValue() var boundValue = Browser.Exists(By.Id("textbox-datetimeoffset-invalid-value")); var mirrorValue = Browser.Exists(By.Id("textbox-datetimeoffset-invalid-mirror")); var expected = new DateTimeOffset(new DateTime(1985, 3, 4), TimeSpan.FromHours(8)); - Assert.Equal(expected, DateTimeOffset.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text)); - Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTimeOffset.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated expected = new DateTime(2000, 1, 2); target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01/02/2000 00:00:00\t"); - Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); + Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); // Modify target to something invalid - the invalid change is reverted // back to the last valid value @@ -1020,16 +1018,16 @@ public void CanBindTextboxDateTimeOffset_InvalidValue() target.SendKeys("05/06X"); Browser.Equal("05/06X", () => target.GetAttribute("value")); target.SendKeys("\t"); - Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(target.GetAttribute("value")).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(boundValue.Text).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); + Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); // Now change it to something valid target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05/06\t"); expected = new DateTime(DateTime.Now.Year, 5, 6); - Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); + Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -1042,8 +1040,8 @@ public void CanBindTextboxDateTimeWithFormat_InvalidValue() var mirrorValue = Browser.Exists(By.Id("textbox-datetime-format-invalid-mirror")); var expected = new DateTime(1985, 3, 4); Assert.Equal("03-04", target.GetAttribute("value")); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target to something invalid - the invalid change is reverted // back to the last valid value @@ -1052,15 +1050,15 @@ public void CanBindTextboxDateTimeWithFormat_InvalidValue() Browser.Equal("05/06", () => target.GetAttribute("value")); target.SendKeys("\t"); Browser.Equal("03-04", () => target.GetAttribute("value")); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Now change it to something valid target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05-06\t"); expected = new DateTime(DateTime.Now.Year, 5, 6); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -1079,8 +1077,8 @@ public void CanBindTextboxNullableDateTimeOffsetWithFormat_InvalidValue() var expected = new DateTimeOffset(new DateTime(DateTime.Now.Year, 1, 2)); target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("01-02\t"); - Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); + Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); // Modify target to something invalid - the invalid change is reverted // back to the last valid value @@ -1088,16 +1086,16 @@ public void CanBindTextboxNullableDateTimeOffsetWithFormat_InvalidValue() target.SendKeys("05/06"); Browser.Equal("05/06", () => target.GetAttribute("value")); target.SendKeys("\t"); - Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(target.GetAttribute("value")).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(boundValue.Text).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); + Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); // Now change it to something valid target.SendKeys(Keys.Control + "a"); // select all target.SendKeys("05-06\t"); expected = new DateTime(DateTime.Now.Year, 5, 6); - Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); - Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); + Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text, CultureInfo.InvariantCulture).DateTime); + Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture).DateTime); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -1109,23 +1107,23 @@ public void CanBindDateTimeLocalTextboxDateTime() var boundValue = Browser.Exists(By.Id("datetime-local-textbox-datetime-value")); var mirrorValue = Browser.Exists(By.Id("datetime-local-textbox-datetime-mirror")); var expected = new DateTime(1985, 3, 4); - Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Clear textbox; value updates to 01/01/0001 because that's the default target.Clear(); expected = default; - Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#datetime-local-textbox-datetime", "2000-01-02T04:05:06"); expected = new DateTime(2000, 1, 2, 04, 05, 06); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -1150,8 +1148,8 @@ public void CanBindDateTimeLocalTextboxNullableDateTime() // element directly. ApplyInputValue("#datetime-local-textbox-nullable-datetime", "2000-01-02T04:05:06"); var expected = new DateTime(2000, 1, 2, 04, 05, 06); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); @@ -1169,25 +1167,25 @@ public void CanBindMonthTextboxDateTime() var boundValue = Browser.Exists(By.Id("month-textbox-datetime-value")); var mirrorValue = Browser.Exists(By.Id("month-textbox-datetime-mirror")); var expected = new DateTime(1985, 3, 1); - Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); // When the value gets displayed the first time it gets truncated to the 1st day, // until there is no change the bound value doesn't get updated. - Assert.Equal(expected.AddDays(3), DateTime.Parse(boundValue.Text)); - Assert.Equal(expected.AddDays(3), DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected.AddDays(3), DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected.AddDays(3), DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Clear textbox; value updates to 01/01/0001 because that's the default target.Clear(); expected = default; - Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#month-textbox-datetime", "2000-02"); expected = new DateTime(2000, 2, 1); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -1212,8 +1210,8 @@ public void CanBindMonthTextboxNullableDateTime() // element directly. ApplyInputValue("#month-textbox-nullable-datetime", "2000-02"); var expected = new DateTime(2000, 2, 1); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); @@ -1231,23 +1229,23 @@ public void CanBindTimeTextboxDateTime() var boundValue = Browser.Exists(By.Id("time-textbox-datetime-value")); var mirrorValue = Browser.Exists(By.Id("time-textbox-datetime-mirror")); var expected = DateTime.Now.Date.AddHours(8).AddMinutes(5); - Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Clear textbox; value updates to 00:00 because that's the default target.Clear(); expected = default; - Browser.Equal(DateTime.Now.Date, () => DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(default, DateTime.Parse(boundValue.Text)); - Assert.Equal(default, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(DateTime.Now.Date, () => DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(default, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(default, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#time-textbox-datetime", "04:05"); expected = DateTime.Now.Date.Add(new TimeSpan(4, 5, 0)); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -1272,8 +1270,8 @@ public void CanBindTimeTextboxNullableDateTime() // element directly. ApplyInputValue("#time-textbox-nullable-datetime", "05:06"); var expected = DateTime.Now.Date.Add(new TimeSpan(05, 06, 0)); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); @@ -1291,23 +1289,23 @@ public void CanBindTimeStepTextboxDateTime() var boundValue = Browser.Exists(By.Id("time-step-textbox-datetime-value")); var mirrorValue = Browser.Exists(By.Id("time-step-textbox-datetime-mirror")); var expected = DateTime.Now.Date.Add(new TimeSpan(8, 5, 30)); - Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(expected, DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Clear textbox; value updates to 00:00 because that's the default target.Clear(); expected = default; - Browser.Equal(DateTime.Now.Date, () => DateTime.Parse(target.GetAttribute("value"))); - Assert.Equal(default, DateTime.Parse(boundValue.Text)); - Assert.Equal(default, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(DateTime.Now.Date, () => DateTime.Parse(target.GetAttribute("value"), CultureInfo.InvariantCulture)); + Assert.Equal(default, DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(default, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // We have to do it this way because the browser gets in the way when sending keys to the input // element directly. ApplyInputValue("#time-step-textbox-datetime", "04:05:06"); expected = DateTime.Now.Date.Add(new TimeSpan(4, 5, 6)); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); } // For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side @@ -1332,8 +1330,8 @@ public void CanBindTimeStepTextboxNullableDateTime() // element directly. ApplyInputValue("#time-step-textbox-nullable-datetime", "05:06"); var expected = DateTime.Now.Date.Add(new TimeSpan(05, 06, 0)); - Browser.Equal(expected, () => DateTime.Parse(boundValue.Text)); - Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"))); + Browser.Equal(expected, () => DateTime.Parse(boundValue.Text, CultureInfo.InvariantCulture)); + Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value"), CultureInfo.InvariantCulture)); // Modify target; verify value is updated and that textboxes linked to the same data are updated target.Clear(); diff --git a/src/Components/test/E2ETest/Tests/BootResourceCachingTest.cs b/src/Components/test/E2ETest/Tests/BootResourceCachingTest.cs index 7cda8292c2a2..fc2549974dab 100644 --- a/src/Components/test/E2ETest/Tests/BootResourceCachingTest.cs +++ b/src/Components/test/E2ETest/Tests/BootResourceCachingTest.cs @@ -46,10 +46,10 @@ public void CachesResourcesAfterFirstLoad() Navigate("/"); WaitUntilLoaded(); var initialResourcesRequested = GetAndClearRequestedPaths(); - Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/blazor.boot.json"))); - Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/dotnet.wasm"))); - Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith(".js"))); - Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith(".dll"))); + Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/blazor.boot.json", StringComparison.Ordinal))); + Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/dotnet.wasm", StringComparison.Ordinal))); + Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith(".js", StringComparison.Ordinal))); + Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith(".dll", StringComparison.Ordinal))); // On subsequent loads, we skip the items referenced from blazor.boot.json // which includes .dll files and dotnet.wasm @@ -57,10 +57,10 @@ public void CachesResourcesAfterFirstLoad() Navigate("/"); WaitUntilLoaded(); var subsequentResourcesRequested = GetAndClearRequestedPaths(); - Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/blazor.boot.json"))); - Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith("/dotnet.wasm"))); - Assert.NotEmpty(subsequentResourcesRequested.Where(path => path.EndsWith(".js"))); - Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith(".dll"))); + Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/blazor.boot.json", StringComparison.Ordinal))); + Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith("/dotnet.wasm", StringComparison.Ordinal))); + Assert.NotEmpty(subsequentResourcesRequested.Where(path => path.EndsWith(".js", StringComparison.Ordinal))); + Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith(".dll", StringComparison.Ordinal))); } [Fact] diff --git a/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs b/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs index 328e3c67df11..1dedce23c1ed 100644 --- a/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs +++ b/src/Components/test/E2ETest/Tests/ErrorNotificationTest.cs @@ -34,7 +34,6 @@ protected override void InitializeAsyncCore() } [Fact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23643")] public void ShowsErrorNotification_OnError_Dismiss() { var errorUi = Browser.Exists(By.Id("blazor-error-ui")); @@ -52,7 +51,6 @@ public void ShowsErrorNotification_OnError_Dismiss() } [Fact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")] public void ShowsErrorNotification_OnError_Reload() { var causeErrorButton = Browser.Exists(By.Id("throw-simple-exception")); diff --git a/src/Components/test/E2ETest/Tests/EventCallbackTest.cs b/src/Components/test/E2ETest/Tests/EventCallbackTest.cs index dbd587068f4d..a985d1532210 100644 --- a/src/Components/test/E2ETest/Tests/EventCallbackTest.cs +++ b/src/Components/test/E2ETest/Tests/EventCallbackTest.cs @@ -30,7 +30,6 @@ protected override void InitializeAsyncCore() } [Theory] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23643")] [InlineData("capturing_lambda")] [InlineData("unbound_lambda")] [InlineData("unbound_lambda_nested")] diff --git a/src/Components/test/E2ETest/Tests/EventTest.cs b/src/Components/test/E2ETest/Tests/EventTest.cs index 218b6a7acaaa..9b676994b374 100644 --- a/src/Components/test/E2ETest/Tests/EventTest.cs +++ b/src/Components/test/E2ETest/Tests/EventTest.cs @@ -177,6 +177,7 @@ public void PreventDefault_AppliesToFormOnSubmitHandlers() } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/25929")] public void PreventDefault_DotNotApplyByDefault() { var appElement = Browser.MountTestComponent(); diff --git a/src/Components/test/E2ETest/Tests/FormsTest.cs b/src/Components/test/E2ETest/Tests/FormsTest.cs index d974ace64f12..cb6cf4691a45 100644 --- a/src/Components/test/E2ETest/Tests/FormsTest.cs +++ b/src/Components/test/E2ETest/Tests/FormsTest.cs @@ -408,7 +408,7 @@ public void CanWireUpINotifyPropertyChangedToEditContext() Browser.Equal("modified valid", () => acceptsTermsInput.GetAttribute("class")); Browser.Equal(string.Empty, () => submissionStatus.Text); submitButton.Click(); - Browser.True(() => submissionStatus.Text.StartsWith("Submitted")); + Browser.True(() => submissionStatus.Text.StartsWith("Submitted", StringComparison.Ordinal)); // Fields can revert to unmodified Browser.Equal("valid", () => userNameInput.GetAttribute("class")); diff --git a/src/Components/test/E2ETest/Tests/GlobalizationTest.cs b/src/Components/test/E2ETest/Tests/GlobalizationTest.cs index 8fca11ec183b..9d1244036bc3 100644 --- a/src/Components/test/E2ETest/Tests/GlobalizationTest.cs +++ b/src/Components/test/E2ETest/Tests/GlobalizationTest.cs @@ -87,7 +87,6 @@ public virtual void CanSetCultureAndParseCultureSensitiveNumbersAndDates(string // We need to do step 4 to make sure that the value we're entering can "stick" in the form field. // We can't use ".Text" because DOM reasons :( [Theory] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23643")] [InlineData("en-US")] [InlineData("fr-FR")] public void CanSetCultureAndParseCultureInvariantNumbersAndDatesWithInputFields(string culture) diff --git a/src/Components/test/E2ETest/Tests/InputFileTest.cs b/src/Components/test/E2ETest/Tests/InputFileTest.cs index 72d346c9ff70..24b1bf2add86 100644 --- a/src/Components/test/E2ETest/Tests/InputFileTest.cs +++ b/src/Components/test/E2ETest/Tests/InputFileTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -9,6 +10,7 @@ using BasicTestApp.FormsTest; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.E2ETesting; using OpenQA.Selenium; using OpenQA.Selenium.Support.Extensions; @@ -57,13 +59,14 @@ public void CanUploadSingleSmallFile() // Validate that the file was uploaded correctly and all fields are present Browser.False(() => string.IsNullOrWhiteSpace(fileNameElement.Text)); - Browser.NotEqual(default, () => DateTimeOffset.Parse(fileLastModifiedElement.Text)); - Browser.Equal(file.Contents.Length.ToString(), () => fileSizeElement.Text); + Browser.NotEqual(default, () => DateTimeOffset.Parse(fileLastModifiedElement.Text, CultureInfo.InvariantCulture)); + Browser.Equal(file.Contents.Length.ToString(CultureInfo.InvariantCulture), () => fileSizeElement.Text); Browser.Equal("text/plain", () => fileContentTypeElement.Text); Browser.Equal(file.Text, () => fileContentElement.Text); } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/26331")] public void CanUploadSingleLargeFile() { // Create a large text file @@ -72,7 +75,7 @@ public void CanUploadSingleLargeFile() for (int i = 0; i < fileContentSizeInBytes; i++) { - contentBuilder.Append((i % 10).ToString()); + contentBuilder.Append((i % 10).ToString(CultureInfo.InvariantCulture)); } var file = TempFile.Create(_tempDirectory, "txt", contentBuilder.ToString()); @@ -90,8 +93,8 @@ public void CanUploadSingleLargeFile() // Validate that the file was uploaded correctly and all fields are present Browser.False(() => string.IsNullOrWhiteSpace(fileNameElement.Text)); - Browser.NotEqual(default, () => DateTimeOffset.Parse(fileLastModifiedElement.Text)); - Browser.Equal(file.Contents.Length.ToString(), () => fileSizeElement.Text); + Browser.NotEqual(default, () => DateTimeOffset.Parse(fileLastModifiedElement.Text, CultureInfo.InvariantCulture)); + Browser.Equal(file.Contents.Length.ToString(CultureInfo.InvariantCulture), () => fileSizeElement.Text); Browser.Equal("text/plain", () => fileContentTypeElement.Text); Browser.Equal(file.Text, () => fileContentElement.Text); } @@ -120,14 +123,15 @@ public void CanUploadMultipleFiles() // Validate that the file was uploaded correctly and all fields are present Browser.False(() => string.IsNullOrWhiteSpace(fileNameElement.Text)); - Browser.NotEqual(default, () => DateTimeOffset.Parse(fileLastModifiedElement.Text)); - Browser.Equal(file.Contents.Length.ToString(), () => fileSizeElement.Text); + Browser.NotEqual(default, () => DateTimeOffset.Parse(fileLastModifiedElement.Text, CultureInfo.InvariantCulture)); + Browser.Equal(file.Contents.Length.ToString(CultureInfo.InvariantCulture), () => fileSizeElement.Text); Browser.Equal("text/plain", () => fileContentTypeElement.Text); Browser.Equal(file.Text, () => fileContentElement.Text); }); } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/25929")] public void CanUploadAndConvertImageFile() { var sourceImageId = "image-source"; diff --git a/src/Components/test/E2ETest/Tests/InteropTest.cs b/src/Components/test/E2ETest/Tests/InteropTest.cs index 4f11502ec40b..bec8607db60d 100644 --- a/src/Components/test/E2ETest/Tests/InteropTest.cs +++ b/src/Components/test/E2ETest/Tests/InteropTest.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Testing; using OpenQA.Selenium; using OpenQA.Selenium.Support.UI; using Xunit; @@ -32,6 +33,7 @@ protected override void InitializeAsyncCore() } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/26288")] public void CanInvokeDotNetMethods() { // Arrange diff --git a/src/Components/test/E2ETest/Tests/KeyTest.cs b/src/Components/test/E2ETest/Tests/KeyTest.cs index 778867f6faf5..71dae5c29032 100644 --- a/src/Components/test/E2ETest/Tests/KeyTest.cs +++ b/src/Components/test/E2ETest/Tests/KeyTest.cs @@ -92,7 +92,6 @@ public void CanInsertUnkeyed() } [Fact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/24190")] public void CanDeleteUnkeyed() { PerformTest( @@ -112,7 +111,6 @@ public void CanDeleteUnkeyed() } [Fact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/24190")] public void CanReorder() { PerformTest( diff --git a/src/Components/test/E2ETest/Tests/RoutingTest.cs b/src/Components/test/E2ETest/Tests/RoutingTest.cs index ef4a065392d3..358bede758c0 100644 --- a/src/Components/test/E2ETest/Tests/RoutingTest.cs +++ b/src/Components/test/E2ETest/Tests/RoutingTest.cs @@ -12,7 +12,6 @@ using Microsoft.AspNetCore.Testing; using OpenQA.Selenium; using OpenQA.Selenium.Interactions; -using OpenQA.Selenium.Support.UI; using Xunit; using Xunit.Abstractions; @@ -341,19 +340,19 @@ public void CanGoBackFromNotAComponent() // First go to some URL on the router var app = Browser.MountTestComponent(); app.FindElement(By.LinkText("Other")).Click(); - Browser.True(() => Browser.Url.EndsWith("/Other")); + Browser.True(() => Browser.Url.EndsWith("/Other", StringComparison.Ordinal)); // Now follow a link out of the SPA entirely app.FindElement(By.LinkText("Not a component")).Click(); Browser.Equal("Not a component!", () => Browser.Exists(By.Id("test-info")).Text); - Browser.True(() => Browser.Url.EndsWith("/NotAComponent.html")); + Browser.True(() => Browser.Url.EndsWith("/NotAComponent.html", StringComparison.Ordinal)); // Now click back // Because of how the tests are structured with the router not appearing until the router // tests are selected, we can only observe the test selector being there, but this is enough // to show we did go back to the right place and the Blazor app started up Browser.Navigate().Back(); - Browser.True(() => Browser.Url.EndsWith("/Other")); + Browser.True(() => Browser.Url.EndsWith("/Other", StringComparison.Ordinal)); Browser.WaitUntilTestSelectorReady(); } @@ -366,7 +365,7 @@ public void CanNavigateProgrammatically() var testSelector = Browser.WaitUntilTestSelectorReady(); app.FindElement(By.Id("do-navigation")).Click(); - Browser.True(() => Browser.Url.EndsWith("/Other")); + Browser.True(() => Browser.Url.EndsWith("/Other", StringComparison.Ordinal)); Browser.Equal("This is another page.", () => app.FindElement(By.Id("test-info")).Text); AssertHighlightedLinks("Other", "Other with base-relative URL (matches all)"); @@ -383,7 +382,7 @@ public void CanNavigateProgrammaticallyWithForceLoad() var testSelector = Browser.WaitUntilTestSelectorReady(); app.FindElement(By.Id("do-navigation-forced")).Click(); - Browser.True(() => Browser.Url.EndsWith("/Other")); + Browser.True(() => Browser.Url.EndsWith("/Other", StringComparison.Ordinal)); // Because this was a full-page load, our element references should no longer be valid Assert.Throws(() => @@ -608,18 +607,30 @@ public void OnNavigate_DoesNotRenderWhileOnNavigateExecuting() Browser.Equal("This is a long page you can scroll.", () => app.FindElement(By.Id("test-info")).Text); } + [Theory] + [InlineData("/WithParameters/Name/Ñoño ñi/LastName/O'Jkl")] + [InlineData("/WithParameters/Name/[Ñoño ñi]/LastName/O'Jkl")] + [InlineData("/other?abc=Ñoño ñi")] + [InlineData("/other?abc=[Ñoño ñi]")] + public void CanArriveAtPageWithSpecialURL(string relativeUrl) + { + SetUrlViaPushState(relativeUrl, true); + var errorUi = Browser.Exists(By.Id("blazor-error-ui")); + Browser.Equal("none", () => errorUi.GetCssValue("display")); + } + private long BrowserScrollY { get => (long)((IJavaScriptExecutor)Browser).ExecuteScript("return window.scrollY"); set => ((IJavaScriptExecutor)Browser).ExecuteScript($"window.scrollTo(0, {value})"); } - private string SetUrlViaPushState(string relativeUri) + private string SetUrlViaPushState(string relativeUri, bool forceLoad = false) { var pathBaseWithoutHash = ServerPathBase.Split('#')[0]; var jsExecutor = (IJavaScriptExecutor)Browser; var absoluteUri = new Uri(_serverFixture.RootUri, $"{pathBaseWithoutHash}{relativeUri}"); - jsExecutor.ExecuteScript($"Blazor.navigateTo('{absoluteUri.ToString().Replace("'", "\\'")}')"); + jsExecutor.ExecuteScript($"Blazor.navigateTo('{absoluteUri.ToString().Replace("'", "\\'")}', {(forceLoad ? "true" : "false")})"); return absoluteUri.AbsoluteUri; } diff --git a/src/Components/test/E2ETest/Tests/VirtualizationTest.cs b/src/Components/test/E2ETest/Tests/VirtualizationTest.cs index f047bbb00288..94a92a19134a 100644 --- a/src/Components/test/E2ETest/Tests/VirtualizationTest.cs +++ b/src/Components/test/E2ETest/Tests/VirtualizationTest.cs @@ -167,6 +167,7 @@ public void RerendersWhenItemSizeShrinks_Async() } [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/25929")] public void CancelsOutdatedRefreshes_Async() { Browser.MountTestComponent(); diff --git a/src/Components/test/E2ETest/Tests/WebAssemblyAuthenticationTests.cs b/src/Components/test/E2ETest/Tests/WebAssemblyAuthenticationTests.cs index 13ebf2e5e5a8..4378506b8e4a 100644 --- a/src/Components/test/E2ETest/Tests/WebAssemblyAuthenticationTests.cs +++ b/src/Components/test/E2ETest/Tests/WebAssemblyAuthenticationTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Data.Common; +using System.Globalization; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; @@ -201,8 +202,8 @@ public void AuthenticatedUser_ProfileIncludesDetails_And_AccessToken() }, payload.Scopes.OrderBy(id => id)); - var currentTime = DateTimeOffset.Parse(Browser.Exists(By.Id("current-time")).Text); - var tokenExpiration = DateTimeOffset.Parse(Browser.Exists(By.Id("access-token-expires")).Text); + var currentTime = DateTimeOffset.Parse(Browser.Exists(By.Id("current-time")).Text, CultureInfo.InvariantCulture); + var tokenExpiration = DateTimeOffset.Parse(Browser.Exists(By.Id("access-token-expires")).Text, CultureInfo.InvariantCulture); Assert.True(currentTime.AddMinutes(50) < tokenExpiration); Assert.True(currentTime.AddMinutes(60) >= tokenExpiration); } diff --git a/src/Components/test/E2ETest/Tests/WebAssemblyConfigurationHostedTest.cs b/src/Components/test/E2ETest/Tests/WebAssemblyConfigurationHostedTest.cs index 245c4c3b6183..62941d7c66ed 100644 --- a/src/Components/test/E2ETest/Tests/WebAssemblyConfigurationHostedTest.cs +++ b/src/Components/test/E2ETest/Tests/WebAssemblyConfigurationHostedTest.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Testing; using OpenQA.Selenium; using Xunit; using Xunit.Abstractions; diff --git a/src/Components/test/testassets/BasicTestApp/Program.cs b/src/Components/test/testassets/BasicTestApp/Program.cs index c3be8fafd7f1..1e75553db716 100644 --- a/src/Components/test/testassets/BasicTestApp/Program.cs +++ b/src/Components/test/testassets/BasicTestApp/Program.cs @@ -33,7 +33,7 @@ public static async Task Main(string[] args) builder.Services.AddAuthorizationCore(options => { options.AddPolicy("NameMustStartWithB", policy => - policy.RequireAssertion(ctx => ctx.User.Identity.Name?.StartsWith("B") ?? false)); + policy.RequireAssertion(ctx => ctx.User.Identity.Name?.StartsWith('B') ?? false)); }); builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging")); diff --git a/src/Components/test/testassets/TestServer/AuthenticationStartup.cs b/src/Components/test/testassets/TestServer/AuthenticationStartup.cs index ca6648d13397..61e81dff5dff 100644 --- a/src/Components/test/testassets/TestServer/AuthenticationStartup.cs +++ b/src/Components/test/testassets/TestServer/AuthenticationStartup.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -32,13 +33,17 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthorization(options => { options.AddPolicy("NameMustStartWithB", policy => - policy.RequireAssertion(ctx => ctx.User.Identity.Name?.StartsWith("B") ?? false)); + policy.RequireAssertion(ctx => ctx.User.Identity.Name?.StartsWith('B') ?? false)); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + var enUs = new CultureInfo("en-US"); + CultureInfo.DefaultThreadCurrentCulture = enUs; + CultureInfo.DefaultThreadCurrentUICulture = enUs; + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); diff --git a/src/Components/test/testassets/TestServer/Components.TestServer.csproj b/src/Components/test/testassets/TestServer/Components.TestServer.csproj index ebe6254a9054..40fb11d8c400 100644 --- a/src/Components/test/testassets/TestServer/Components.TestServer.csproj +++ b/src/Components/test/testassets/TestServer/Components.TestServer.csproj @@ -2,9 +2,12 @@ $(DefaultNetCoreTargetFramework) + + + true - + diff --git a/src/Components/test/testassets/TestServer/Controllers/CookieController.cs b/src/Components/test/testassets/TestServer/Controllers/CookieController.cs index 72d5bd17e9ad..58a45a77f485 100644 --- a/src/Components/test/testassets/TestServer/Controllers/CookieController.cs +++ b/src/Components/test/testassets/TestServer/Controllers/CookieController.cs @@ -1,4 +1,8 @@ -using Microsoft.AspNetCore.Cors; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Globalization; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; namespace TestServer.Controllers @@ -20,11 +24,11 @@ public string Increment() var counter = 0; if (Request.Cookies.TryGetValue(cookieKey, out var incomingValue)) { - counter = int.Parse(incomingValue); + counter = int.Parse(incomingValue, CultureInfo.InvariantCulture); } counter++; - Response.Cookies.Append(cookieKey, counter.ToString()); + Response.Cookies.Append(cookieKey, counter.ToString(CultureInfo.InvariantCulture)); return $"Counter value is {counter}"; } diff --git a/src/Components/test/testassets/TestServer/CorsStartup.cs b/src/Components/test/testassets/TestServer/CorsStartup.cs index 7459d9fb8698..df447c8d671e 100644 --- a/src/Components/test/testassets/TestServer/CorsStartup.cs +++ b/src/Components/test/testassets/TestServer/CorsStartup.cs @@ -1,3 +1,8 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Globalization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -27,7 +32,7 @@ public void ConfigureServices(IServiceCollection services) // specify explicitly which origin we want to allow. options.AddPolicy("AllowAll", policy => policy - .SetIsOriginAllowed(host => host.StartsWith("http://localhost:") || host.StartsWith("http://127.0.0.1:")) + .SetIsOriginAllowed(host => host.StartsWith("http://localhost:", StringComparison.Ordinal) || host.StartsWith("http://127.0.0.1:", StringComparison.Ordinal)) .AllowAnyHeader() .WithExposedHeaders("MyCustomHeader") .AllowAnyMethod() @@ -38,6 +43,10 @@ public void ConfigureServices(IServiceCollection services) // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + var enUs = new CultureInfo("en-US"); + CultureInfo.DefaultThreadCurrentCulture = enUs; + CultureInfo.DefaultThreadCurrentUICulture = enUs; + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); diff --git a/src/Components/test/testassets/TestServer/MultipleComponents.cs b/src/Components/test/testassets/TestServer/MultipleComponents.cs index 3a3bf468a62a..a965cbfd086b 100644 --- a/src/Components/test/testassets/TestServer/MultipleComponents.cs +++ b/src/Components/test/testassets/TestServer/MultipleComponents.cs @@ -1,3 +1,4 @@ +using System.Globalization; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -27,6 +28,10 @@ public void ConfigureServices(IServiceCollection services) // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + var enUs = new CultureInfo("en-US"); + CultureInfo.DefaultThreadCurrentCulture = enUs; + CultureInfo.DefaultThreadCurrentUICulture = enUs; + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); diff --git a/src/Components/test/testassets/TestServer/PrerenderedStartup.cs b/src/Components/test/testassets/TestServer/PrerenderedStartup.cs index c4d7ad3c94dd..0a3e28bf3418 100644 --- a/src/Components/test/testassets/TestServer/PrerenderedStartup.cs +++ b/src/Components/test/testassets/TestServer/PrerenderedStartup.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.AspNetCore.Components.WebAssembly.Services; +using System.Globalization; namespace TestServer { @@ -29,6 +30,10 @@ public void ConfigureServices(IServiceCollection services) // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + var enUs = new CultureInfo("en-US"); + CultureInfo.DefaultThreadCurrentCulture = enUs; + CultureInfo.DefaultThreadCurrentUICulture = enUs; + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); diff --git a/src/Components/test/testassets/TestServer/ServerStartup.cs b/src/Components/test/testassets/TestServer/ServerStartup.cs index 6b4c5668bdb1..acc321be06a6 100644 --- a/src/Components/test/testassets/TestServer/ServerStartup.cs +++ b/src/Components/test/testassets/TestServer/ServerStartup.cs @@ -1,3 +1,4 @@ +using System.Globalization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -25,6 +26,10 @@ public void ConfigureServices(IServiceCollection services) // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + var enUs = new CultureInfo("en-US"); + CultureInfo.DefaultThreadCurrentCulture = enUs; + CultureInfo.DefaultThreadCurrentUICulture = enUs; + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); diff --git a/src/Components/test/testassets/TestServer/Startup.cs b/src/Components/test/testassets/TestServer/Startup.cs index f110edfaddac..23d927cb4a74 100644 --- a/src/Components/test/testassets/TestServer/Startup.cs +++ b/src/Components/test/testassets/TestServer/Startup.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -26,6 +27,10 @@ public void ConfigureServices(IServiceCollection services) // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + var enUs = new CultureInfo("en-US"); + CultureInfo.DefaultThreadCurrentCulture = enUs; + CultureInfo.DefaultThreadCurrentUICulture = enUs; + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); diff --git a/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs b/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs index a65b87c23096..b11cbdfe59a4 100644 --- a/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs +++ b/src/Components/test/testassets/TestServer/StartupWithMapFallbackToClientSideBlazor.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -25,6 +26,10 @@ public void ConfigureServices(IServiceCollection services) public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + var enUs = new CultureInfo("en-US"); + CultureInfo.DefaultThreadCurrentCulture = enUs; + CultureInfo.DefaultThreadCurrentUICulture = enUs; + if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); diff --git a/src/Configuration.KeyPerFile/src/KeyPerFileConfigurationProvider.cs b/src/Configuration.KeyPerFile/src/KeyPerFileConfigurationProvider.cs index f586896fc275..6d4e318b1540 100644 --- a/src/Configuration.KeyPerFile/src/KeyPerFileConfigurationProvider.cs +++ b/src/Configuration.KeyPerFile/src/KeyPerFileConfigurationProvider.cs @@ -40,7 +40,7 @@ private static string NormalizeKey(string key) => key.Replace("__", ConfigurationPath.KeyDelimiter); private static string TrimNewLine(string value) - => value.EndsWith(Environment.NewLine) + => value.EndsWith(Environment.NewLine, StringComparison.Ordinal) ? value.Substring(0, value.Length - Environment.NewLine.Length) : value; diff --git a/src/Configuration.KeyPerFile/src/KeyPerFileConfigurationSource.cs b/src/Configuration.KeyPerFile/src/KeyPerFileConfigurationSource.cs index 2b64d5a8dda7..f8f84f7b276c 100644 --- a/src/Configuration.KeyPerFile/src/KeyPerFileConfigurationSource.cs +++ b/src/Configuration.KeyPerFile/src/KeyPerFileConfigurationSource.cs @@ -13,7 +13,7 @@ public class KeyPerFileConfigurationSource : IConfigurationSource /// Constructor; ///
public KeyPerFileConfigurationSource() - => IgnoreCondition = s => IgnorePrefix != null && s.StartsWith(IgnorePrefix); + => IgnoreCondition = s => IgnorePrefix != null && s.StartsWith(IgnorePrefix, StringComparison.Ordinal); /// /// The FileProvider whos root "/" directory files will be used as configuration data. diff --git a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs index 094832e43c0e..a73d52793ee2 100644 --- a/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs +++ b/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs @@ -145,7 +145,7 @@ public IKey CreateNewKey(DateTimeOffset activationDate, DateTimeOffset expiratio private static string DateTimeOffsetToFilenameSafeString(DateTimeOffset dateTime) { // similar to the XML format for dates, but with punctuation stripped - return dateTime.UtcDateTime.ToString("yyyyMMddTHHmmssFFFFFFFZ"); + return dateTime.UtcDateTime.ToString("yyyyMMddTHHmmssFFFFFFFZ", CultureInfo.InvariantCulture); } public IReadOnlyCollection GetAllKeys() diff --git a/src/DataProtection/DataProtection/test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs b/src/DataProtection/DataProtection/test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs index 69cc556e6bf6..ef2604e8ec2e 100644 --- a/src/DataProtection/DataProtection/test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs +++ b/src/DataProtection/DataProtection/test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializerTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Security.Cryptography; using System.Xml.Linq; using Microsoft.AspNetCore.DataProtection.KeyManagement; @@ -30,7 +31,9 @@ public void ImportFromXml_BuiltInTypes_CreatesAppropriateDescriptor(Type encrypt "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret()); var control = CreateEncryptorInstanceFromDescriptor(descriptor); - string xml = string.Format(@" + string xml = string.Format( + CultureInfo.InvariantCulture, + @" @@ -64,7 +67,9 @@ public void ImportFromXml_CustomType_CreatesAppropriateDescriptor() "k88VrwGLINfVAqzlAp7U4EAjdlmUG17c756McQGdjHU8Ajkfc/A3YOKdqlMcF6dXaIxATED+g2f62wkRRRRRzA==".ToSecret()); var control = CreateEncryptorInstanceFromDescriptor(descriptor); - string xml = string.Format(@" + string xml = string.Format( + CultureInfo.InvariantCulture, + @" diff --git a/src/DataProtection/DataProtection/test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorTests.cs b/src/DataProtection/DataProtection/test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorTests.cs index 4e4f4534484e..6d92fcf7ddbc 100644 --- a/src/DataProtection/DataProtection/test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorTests.cs +++ b/src/DataProtection/DataProtection/test/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Security.Cryptography; using Xunit; @@ -26,7 +27,9 @@ public void ExportToXml_CustomTypes_ProducesCorrectPayload() // Assert Assert.Equal(typeof(ManagedAuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); - string expectedXml = string.Format(@" + string expectedXml = string.Format( + CultureInfo.InvariantCulture, + @" @@ -59,7 +62,9 @@ public void ExportToXml_BuiltInTypes_ProducesCorrectPayload(Type encryptionAlgor // Assert Assert.Equal(typeof(ManagedAuthenticatedEncryptorDescriptorDeserializer), retVal.DeserializerType); - string expectedXml = string.Format(@" + string expectedXml = string.Format( + CultureInfo.InvariantCulture, + @" diff --git a/src/DataProtection/DataProtection/test/KeyManagement/XmlKeyManagerTests.cs b/src/DataProtection/DataProtection/test/KeyManagement/XmlKeyManagerTests.cs index c6a2e068a3fb..efb107feca72 100644 --- a/src/DataProtection/DataProtection/test/KeyManagement/XmlKeyManagerTests.cs +++ b/src/DataProtection/DataProtection/test/KeyManagement/XmlKeyManagerTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; @@ -136,7 +137,9 @@ public void CreateNewKey_Internal_NoEscrowOrEncryption() Assert.Same(expectedAuthenticatedEncryptor, testEncryptorFactory.CreateEncryptorInstance(newKey)); // Finally, was the correct element stored in the repository? - string expectedXml = string.Format(@" + string expectedXml = string.Format( + CultureInfo.InvariantCulture, + @" {1} {2} @@ -233,7 +236,9 @@ public void CreateNewKey_Internal_WithEscrowAndEncryption() // Was the correct element stored in escrow? // This should not have gone through the encryptor. - string expectedEscrowXml = string.Format(@" + string expectedEscrowXml = string.Format( + CultureInfo.InvariantCulture, + @" {1} {2} @@ -255,7 +260,9 @@ public void CreateNewKey_Internal_WithEscrowAndEncryption() // Finally, was the correct element stored in the repository? // This should have gone through the encryptor (which we set to be the null encryptor in this test) - string expectedRepositoryXml = String.Format(@" + string expectedRepositoryXml = String.Format( + CultureInfo.InvariantCulture, + @" {2} {3} @@ -696,7 +703,9 @@ public void RevokeSingleKey_Internal() Assert.False(secondCancellationToken.IsCancellationRequested); // Was the correct element stored in the repository? - var expectedRepositoryXml = string.Format(@" + var expectedRepositoryXml = string.Format( + CultureInfo.InvariantCulture, + @" {0} diff --git a/src/DataProtection/DataProtection/test/XmlAssert.cs b/src/DataProtection/DataProtection/test/XmlAssert.cs index 3bd5ccdc161f..d6febaa0b378 100644 --- a/src/DataProtection/DataProtection/test/XmlAssert.cs +++ b/src/DataProtection/DataProtection/test/XmlAssert.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Xml.Linq; using Xunit; @@ -124,7 +125,7 @@ private static bool ShouldIncludeNodeDuringComparison(XNode node) return true; // relevant } - throw new NotSupportedException(string.Format("Node of type '{0}' is not supported.", node.GetType().Name)); + throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Node of type '{0}' is not supported.", node.GetType().Name)); } } diff --git a/src/DataProtection/DataProtection/test/XmlEncryption/XmlEncryptionExtensionsTests.cs b/src/DataProtection/DataProtection/test/XmlEncryption/XmlEncryptionExtensionsTests.cs index bf3c455b5a52..7abe4972df56 100644 --- a/src/DataProtection/DataProtection/test/XmlEncryption/XmlEncryptionExtensionsTests.cs +++ b/src/DataProtection/DataProtection/test/XmlEncryption/XmlEncryptionExtensionsTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using System.Xml.Linq; using Microsoft.AspNetCore.DataProtection.Internal; @@ -151,7 +152,9 @@ public void EncryptIfNecessary_MultipleNodesRequireEncryption_Success() "); - var expected = string.Format(@" + var expected = string.Format( + CultureInfo.InvariantCulture, + @" @@ -194,7 +197,9 @@ public void EncryptIfNecessary_NullEncryptorWithRecursion_NoStackDive_Success() "); - var expected = string.Format(@" + var expected = string.Format( + CultureInfo.InvariantCulture, + @" diff --git a/src/DataProtection/Extensions/test/DataProtectionProviderTests.cs b/src/DataProtection/Extensions/test/DataProtectionProviderTests.cs index 951b0030636d..8fb700d452da 100644 --- a/src/DataProtection/Extensions/test/DataProtectionProviderTests.cs +++ b/src/DataProtection/Extensions/test/DataProtectionProviderTests.cs @@ -115,7 +115,7 @@ public void System_UsesProvidedDirectory_WithConfigurationCallback() [ConditionalFact] [X509StoreIsAvailable(StoreName.My, StoreLocation.CurrentUser)] - [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720 and https://github.com/dotnet/aspnetcore/issues/26871", Queues = "All.OSX;Windows.10.Arm64.Open")] public void System_UsesProvidedDirectoryAndCertificate() { var filePath = Path.Combine(GetTestFilesPath(), "TestCert.pfx"); diff --git a/src/Features/JsonPatch/src/JsonPatchDocumentOfT.cs b/src/Features/JsonPatch/src/JsonPatchDocumentOfT.cs index eb3276ffa187..6ccefe3808ce 100644 --- a/src/Features/JsonPatch/src/JsonPatchDocumentOfT.cs +++ b/src/Features/JsonPatch/src/JsonPatchDocumentOfT.cs @@ -85,7 +85,7 @@ public JsonPatchDocument Add( Operations.Add(new Operation( "add", - GetPath(path, position.ToString()), + GetPath(path, position.ToString(CultureInfo.InvariantCulture)), from: null, value: value)); @@ -149,7 +149,7 @@ public JsonPatchDocument Remove(Expression( "remove", - GetPath(path, position.ToString()), + GetPath(path, position.ToString(CultureInfo.InvariantCulture)), from: null)); return this; @@ -217,7 +217,7 @@ public JsonPatchDocument Replace(Expression( "replace", - GetPath(path, position.ToString()), + GetPath(path, position.ToString(CultureInfo.InvariantCulture)), from: null, value: value)); @@ -288,7 +288,7 @@ public JsonPatchDocument Test(Expression( "test", - GetPath(path, position.ToString()), + GetPath(path, position.ToString(CultureInfo.InvariantCulture)), from: null, value: value)); @@ -373,7 +373,7 @@ public JsonPatchDocument Move( Operations.Add(new Operation( "move", GetPath(path, null), - GetPath(from, positionFrom.ToString()))); + GetPath(from, positionFrom.ToString(CultureInfo.InvariantCulture)))); return this; } @@ -403,7 +403,7 @@ public JsonPatchDocument Move( Operations.Add(new Operation( "move", - GetPath(path, positionTo.ToString()), + GetPath(path, positionTo.ToString(CultureInfo.InvariantCulture)), GetPath(from, null))); return this; @@ -436,8 +436,8 @@ public JsonPatchDocument Move( Operations.Add(new Operation( "move", - GetPath(path, positionTo.ToString()), - GetPath(from, positionFrom.ToString()))); + GetPath(path, positionTo.ToString(CultureInfo.InvariantCulture)), + GetPath(from, positionFrom.ToString(CultureInfo.InvariantCulture)))); return this; } @@ -468,7 +468,7 @@ public JsonPatchDocument Move( Operations.Add(new Operation( "move", GetPath(path, "-"), - GetPath(from, positionFrom.ToString()))); + GetPath(from, positionFrom.ToString(CultureInfo.InvariantCulture)))); return this; } @@ -557,7 +557,7 @@ public JsonPatchDocument Copy( Operations.Add(new Operation( "copy", GetPath(path, null), - GetPath(from, positionFrom.ToString()))); + GetPath(from, positionFrom.ToString(CultureInfo.InvariantCulture)))); return this; } @@ -587,7 +587,7 @@ public JsonPatchDocument Copy( Operations.Add(new Operation( "copy", - GetPath(path, positionTo.ToString()), + GetPath(path, positionTo.ToString(CultureInfo.InvariantCulture)), GetPath(from, null))); return this; @@ -620,8 +620,8 @@ public JsonPatchDocument Copy( Operations.Add(new Operation( "copy", - GetPath(path, positionTo.ToString()), - GetPath(from, positionFrom.ToString()))); + GetPath(path, positionTo.ToString(CultureInfo.InvariantCulture)), + GetPath(from, positionFrom.ToString(CultureInfo.InvariantCulture)))); return this; } @@ -652,7 +652,7 @@ public JsonPatchDocument Copy( Operations.Add(new Operation( "copy", GetPath(path, "-"), - GetPath(from, positionFrom.ToString()))); + GetPath(from, positionFrom.ToString(CultureInfo.InvariantCulture)))); return this; } diff --git a/src/Features/JsonPatch/test/Internal/DictionaryAdapterTest.cs b/src/Features/JsonPatch/test/Internal/DictionaryAdapterTest.cs index a0dcd82ab017..e055009b8274 100644 --- a/src/Features/JsonPatch/test/Internal/DictionaryAdapterTest.cs +++ b/src/Features/JsonPatch/test/Internal/DictionaryAdapterTest.cs @@ -1,8 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; +using System.Globalization; using Newtonsoft.Json.Serialization; using Xunit; @@ -41,7 +42,7 @@ public void Add_IntKeyWhichAlreadyExists_ReplacesExistingValue() var resolver = new DefaultContractResolver(); // Act - var addStatus = dictionaryAdapter.TryAdd(dictionary, intKey.ToString(), resolver, "James", out var message); + var addStatus = dictionaryAdapter.TryAdd(dictionary, intKey.ToString(CultureInfo.InvariantCulture), resolver, "James", out var message); // Assert Assert.True(addStatus); @@ -60,7 +61,7 @@ public void GetInvalidKey_ThrowsInvalidPathSegmentException() var dictionary = new Dictionary(); // Act - var addStatus = dictionaryAdapter.TryAdd(dictionary, key.ToString(), resolver, "James", out var message); + var addStatus = dictionaryAdapter.TryAdd(dictionary, key.ToString(CultureInfo.InvariantCulture), resolver, "James", out var message); // Assert Assert.True(addStatus); @@ -97,7 +98,7 @@ public void Get_UsingCaseSensitiveKey_FailureScenario() Assert.Equal("James", dictionary[nameKey]); // Act - var getStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpper(), resolver, out var outValue, out message); + var getStatus = dictionaryAdapter.TryGet(dictionary, nameKey.ToUpperInvariant(), resolver, out var outValue, out message); // Assert Assert.False(getStatus); diff --git a/src/Features/JsonPatch/test/Internal/ListAdapterTest.cs b/src/Features/JsonPatch/test/Internal/ListAdapterTest.cs index f31e57541b02..65c87bab1830 100644 --- a/src/Features/JsonPatch/test/Internal/ListAdapterTest.cs +++ b/src/Features/JsonPatch/test/Internal/ListAdapterTest.cs @@ -1,8 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections; using System.Collections.Generic; +using System.Globalization; using Moq; using Newtonsoft.Json.Serialization; using Xunit; @@ -52,7 +53,7 @@ public void Add_WithIndexSameAsNumberOfElements_Works() var resolver = new Mock(MockBehavior.Strict); var targetObject = new List() { "James", "Mike" }; var listAdapter = new ListAdapter(); - var position = targetObject.Count.ToString(); + var position = targetObject.Count.ToString(CultureInfo.InvariantCulture); // Act var addStatus = listAdapter.TryAdd(targetObject, position, resolver.Object, "Rob", out var message); diff --git a/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj b/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj index 2e10f9ff36eb..1b2286889fbb 100644 --- a/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj +++ b/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj @@ -92,7 +92,7 @@ This package is an internal implementation of the .NET Core SDK and is not meant : %3B - x64_arm + x64_arm x64_arm64 x86_arm diff --git a/src/Framework/Directory.Build.props b/src/Framework/Directory.Build.props index 555b1633d650..026b3c7047aa 100644 --- a/src/Framework/Directory.Build.props +++ b/src/Framework/Directory.Build.props @@ -7,15 +7,15 @@ PlatformManifest.txt $(ArtifactsObjDir)$(PlatformManifestFileName) - - $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).0 + + $(AspNetCoreMajorMinorVersion).0 $(ReferencePackSharedFxVersion)-$(VersionSuffix) - + diff --git a/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj b/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj index 3a594e0f301f..bee9ff9066d4 100644 --- a/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj +++ b/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj @@ -16,6 +16,10 @@ <_Parameter1>SharedFxVersion <_Parameter2>$(SharedFxVersion) + + <_Parameter1>DefaultNetCoreTargetFramework + <_Parameter2>$(DefaultNetCoreTargetFramework) + <_Parameter1>TargetRuntimeIdentifier <_Parameter2>$(TargetRuntimeIdentifier) diff --git a/src/Framework/test/SharedFxTests.cs b/src/Framework/test/SharedFxTests.cs index 227c53140c0e..a6753f803302 100644 --- a/src/Framework/test/SharedFxTests.cs +++ b/src/Framework/test/SharedFxTests.cs @@ -27,7 +27,7 @@ public class SharedFxTests public SharedFxTests(ITestOutputHelper output) { _output = output; - _expectedTfm = "net" + TestData.GetSharedFxVersion().Substring(0, 3); + _expectedTfm = TestData.GetDefaultNetCoreTargetFramework(); _expectedRid = TestData.GetSharedFxRuntimeIdentifier(); _sharedFxRoot = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ASPNET_RUNTIME_PATH")) ? Path.Combine(TestData.GetTestDataValue("SharedFrameworkLayoutRoot"), "shared", "Microsoft.AspNetCore.App", TestData.GetTestDataValue("RuntimePackageVersion")) @@ -108,7 +108,7 @@ public void SharedFrameworkContainsValidDepsJson() { var depsFilePath = Path.Combine(_sharedFxRoot, "Microsoft.AspNetCore.App.deps.json"); - var target = $".NETCoreApp,Version=v{TestData.GetSharedFxVersion().Substring(0, 3)}/{_expectedRid}"; + var target = $".NETCoreApp,Version=v{_expectedTfm.Substring(3)}/{_expectedRid}"; var ridPackageId = $"Microsoft.AspNetCore.App.Runtime.{_expectedRid}"; var libraryId = $"{ridPackageId}/{TestData.GetTestDataValue("RuntimePackageVersion")}"; @@ -192,7 +192,7 @@ public void SharedFrameworkAssemblyReferencesHaveExpectedAssemblyVersions() using var fileStream = File.OpenRead(path); using var peReader = new PEReader(fileStream, PEStreamOptions.Default); var reader = peReader.GetMetadataReader(MetadataReaderOptions.Default); - + Assert.All(reader.AssemblyReferences, handle => { var reference = reader.GetAssemblyReference(handle); @@ -290,7 +290,7 @@ public void RuntimeListListsContainsCorrectPaths() ZipArchive archive = ZipFile.OpenRead(sharedFxPath); var actualPaths = archive.Entries - .Where(i => i.FullName.EndsWith(".dll")) + .Where(i => i.FullName.EndsWith(".dll", StringComparison.Ordinal)) .Select(i => i.FullName).ToHashSet(); var expectedPaths = runtimeListEntries.Select(i => i.Attribute("Path").Value).ToHashSet(); diff --git a/src/Framework/test/TargetingPackTests.cs b/src/Framework/test/TargetingPackTests.cs index 8d9f02524e24..5f34153949c5 100644 --- a/src/Framework/test/TargetingPackTests.cs +++ b/src/Framework/test/TargetingPackTests.cs @@ -29,7 +29,7 @@ public TargetingPackTests(ITestOutputHelper output) { _output = output; _expectedRid = TestData.GetSharedFxRuntimeIdentifier(); - _targetingPackTfm = "net" + TestData.GetSharedFxVersion().Substring(0, 3); + _targetingPackTfm = TestData.GetDefaultNetCoreTargetFramework(); var root = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix")) ? TestData.GetTestDataValue("TargetingPackLayoutRoot") : Environment.GetEnvironmentVariable("DOTNET_ROOT"); @@ -370,7 +370,7 @@ public void FrameworkListListsContainsCorrectPaths() ZipArchive archive = ZipFile.OpenRead(targetingPackPath); var actualPaths = archive.Entries - .Where(i => i.FullName.EndsWith(".dll")) + .Where(i => i.FullName.EndsWith(".dll", StringComparison.Ordinal)) .Select(i => i.FullName).ToHashSet(); var expectedPaths = frameworkListEntries.Select(i => i.Attribute("Path").Value).ToHashSet(); diff --git a/src/Framework/test/TestData.cs b/src/Framework/test/TestData.cs index 2271d24ece6f..e73cd74901a3 100644 --- a/src/Framework/test/TestData.cs +++ b/src/Framework/test/TestData.cs @@ -151,83 +151,83 @@ static TestData() }; ListedTargetingPackAssemblies = new SortedDictionary { - { "Microsoft.AspNetCore", "5.0.0.0" }, - { "Microsoft.AspNetCore.Antiforgery", "5.0.0.0" }, - { "Microsoft.AspNetCore.Authentication", "5.0.0.0" }, - { "Microsoft.AspNetCore.Authentication.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Authentication.Cookies", "5.0.0.0" }, - { "Microsoft.AspNetCore.Authentication.Core", "5.0.0.0" }, - { "Microsoft.AspNetCore.Authentication.OAuth", "5.0.0.0" }, - { "Microsoft.AspNetCore.Authorization", "5.0.0.0" }, - { "Microsoft.AspNetCore.Authorization.Policy", "5.0.0.0" }, - { "Microsoft.AspNetCore.Components", "5.0.0.0" }, - { "Microsoft.AspNetCore.Components.Authorization", "5.0.0.0" }, - { "Microsoft.AspNetCore.Components.Forms", "5.0.0.0" }, - { "Microsoft.AspNetCore.Components.Server", "5.0.0.0" }, - { "Microsoft.AspNetCore.Components.Web", "5.0.0.0" }, - { "Microsoft.AspNetCore.Connections.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.CookiePolicy", "5.0.0.0" }, - { "Microsoft.AspNetCore.Cors", "5.0.0.0" }, - { "Microsoft.AspNetCore.Cryptography.Internal", "5.0.0.0" }, - { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "5.0.0.0" }, - { "Microsoft.AspNetCore.DataProtection", "5.0.0.0" }, - { "Microsoft.AspNetCore.DataProtection.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.DataProtection.Extensions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Diagnostics", "5.0.0.0" }, - { "Microsoft.AspNetCore.Diagnostics.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "5.0.0.0" }, - { "Microsoft.AspNetCore.HostFiltering", "5.0.0.0" }, - { "Microsoft.AspNetCore.Hosting", "5.0.0.0" }, - { "Microsoft.AspNetCore.Hosting.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Html.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Http", "5.0.0.0" }, - { "Microsoft.AspNetCore.Http.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Http.Connections", "5.0.0.0" }, - { "Microsoft.AspNetCore.Http.Connections.Common", "5.0.0.0" }, - { "Microsoft.AspNetCore.Http.Extensions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Http.Features", "5.0.0.0" }, - { "Microsoft.AspNetCore.HttpOverrides", "5.0.0.0" }, - { "Microsoft.AspNetCore.HttpsPolicy", "5.0.0.0" }, - { "Microsoft.AspNetCore.Identity", "5.0.0.0" }, - { "Microsoft.AspNetCore.Localization", "5.0.0.0" }, - { "Microsoft.AspNetCore.Localization.Routing", "5.0.0.0" }, - { "Microsoft.AspNetCore.Metadata", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.ApiExplorer", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.Core", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.Cors", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.DataAnnotations", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.Formatters.Json", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.Localization", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.Razor", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.RazorPages", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.TagHelpers", "5.0.0.0" }, - { "Microsoft.AspNetCore.Mvc.ViewFeatures", "5.0.0.0" }, - { "Microsoft.AspNetCore.Razor", "5.0.0.0" }, - { "Microsoft.AspNetCore.Razor.Runtime", "5.0.0.0" }, - { "Microsoft.AspNetCore.ResponseCaching", "5.0.0.0" }, - { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.ResponseCompression", "5.0.0.0" }, - { "Microsoft.AspNetCore.Rewrite", "5.0.0.0" }, - { "Microsoft.AspNetCore.Routing", "5.0.0.0" }, - { "Microsoft.AspNetCore.Routing.Abstractions", "5.0.0.0" }, - { "Microsoft.AspNetCore.Server.HttpSys", "5.0.0.0" }, - { "Microsoft.AspNetCore.Server.IIS", "5.0.0.0" }, - { "Microsoft.AspNetCore.Server.IISIntegration", "5.0.0.0" }, - { "Microsoft.AspNetCore.Server.Kestrel", "5.0.0.0" }, - { "Microsoft.AspNetCore.Server.Kestrel.Core", "5.0.0.0" }, - { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "5.0.0.0" }, - { "Microsoft.AspNetCore.Session", "5.0.0.0" }, - { "Microsoft.AspNetCore.SignalR", "5.0.0.0" }, - { "Microsoft.AspNetCore.SignalR.Common", "5.0.0.0" }, - { "Microsoft.AspNetCore.SignalR.Core", "5.0.0.0" }, - { "Microsoft.AspNetCore.SignalR.Protocols.Json", "5.0.0.0" }, - { "Microsoft.AspNetCore.StaticFiles", "5.0.0.0" }, - { "Microsoft.AspNetCore.WebSockets", "5.0.0.0" }, - { "Microsoft.AspNetCore.WebUtilities", "5.0.0.0" }, + { "Microsoft.AspNetCore", "6.0.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "6.0.0.0" }, + { "Microsoft.AspNetCore.Authentication", "6.0.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "6.0.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "6.0.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "6.0.0.0" }, + { "Microsoft.AspNetCore.Authorization", "6.0.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "6.0.0.0" }, + { "Microsoft.AspNetCore.Components", "6.0.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "6.0.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "6.0.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "6.0.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "6.0.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "6.0.0.0" }, + { "Microsoft.AspNetCore.Cors", "6.0.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "6.0.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "6.0.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "6.0.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "6.0.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "6.0.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "6.0.0.0" }, + { "Microsoft.AspNetCore.Hosting", "6.0.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Http", "6.0.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "6.0.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "6.0.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "6.0.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "6.0.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "6.0.0.0" }, + { "Microsoft.AspNetCore.Identity", "6.0.0.0" }, + { "Microsoft.AspNetCore.Localization", "6.0.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "6.0.0.0" }, + { "Microsoft.AspNetCore.Metadata", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "6.0.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "6.0.0.0" }, + { "Microsoft.AspNetCore.Razor", "6.0.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "6.0.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "6.0.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "6.0.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "6.0.0.0" }, + { "Microsoft.AspNetCore.Routing", "6.0.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "6.0.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "6.0.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "6.0.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "6.0.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "6.0.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "6.0.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "6.0.0.0" }, + { "Microsoft.AspNetCore.Session", "6.0.0.0" }, + { "Microsoft.AspNetCore.SignalR", "6.0.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "6.0.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "6.0.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "6.0.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "6.0.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "6.0.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "6.0.0.0" }, { "Microsoft.Extensions.Caching.Abstractions", "5.0.0.0" }, { "Microsoft.Extensions.Caching.Memory", "5.0.0.0" }, { "Microsoft.Extensions.Configuration", "5.0.0.0" }, @@ -238,25 +238,25 @@ static TestData() { "Microsoft.Extensions.Configuration.FileExtensions", "5.0.0.0" }, { "Microsoft.Extensions.Configuration.Ini", "5.0.0.0" }, { "Microsoft.Extensions.Configuration.Json", "5.0.0.0" }, - { "Microsoft.Extensions.Configuration.KeyPerFile", "5.0.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "6.0.0.0" }, { "Microsoft.Extensions.Configuration.UserSecrets", "5.0.0.0" }, { "Microsoft.Extensions.Configuration.Xml", "5.0.0.0" }, { "Microsoft.Extensions.DependencyInjection", "5.0.0.0" }, { "Microsoft.Extensions.DependencyInjection.Abstractions", "5.0.0.0" }, - { "Microsoft.Extensions.Diagnostics.HealthChecks", "5.0.0.0" }, - { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "5.0.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "6.0.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "6.0.0.0" }, { "Microsoft.Extensions.FileProviders.Abstractions", "5.0.0.0" }, { "Microsoft.Extensions.FileProviders.Composite", "5.0.0.0" }, - { "Microsoft.Extensions.FileProviders.Embedded", "5.0.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "6.0.0.0" }, { "Microsoft.Extensions.FileProviders.Physical", "5.0.0.0" }, { "Microsoft.Extensions.FileSystemGlobbing", "5.0.0.0" }, { "Microsoft.Extensions.Hosting", "5.0.0.0" }, { "Microsoft.Extensions.Hosting.Abstractions", "5.0.0.0" }, { "Microsoft.Extensions.Http", "5.0.0.0" }, - { "Microsoft.Extensions.Identity.Core", "5.0.0.0" }, - { "Microsoft.Extensions.Identity.Stores", "5.0.0.0" }, - { "Microsoft.Extensions.Localization", "5.0.0.0" }, - { "Microsoft.Extensions.Localization.Abstractions", "5.0.0.0" }, + { "Microsoft.Extensions.Identity.Core", "6.0.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "6.0.0.0" }, + { "Microsoft.Extensions.Localization", "6.0.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "6.0.0.0" }, { "Microsoft.Extensions.Logging", "5.0.0.0" }, { "Microsoft.Extensions.Logging.Abstractions", "5.0.0.0" }, { "Microsoft.Extensions.Logging.Configuration", "5.0.0.0" }, @@ -265,14 +265,14 @@ static TestData() { "Microsoft.Extensions.Logging.EventLog", "5.0.0.0" }, { "Microsoft.Extensions.Logging.EventSource", "5.0.0.0" }, { "Microsoft.Extensions.Logging.TraceSource", "5.0.0.0" }, - { "Microsoft.Extensions.ObjectPool", "5.0.0.0" }, + { "Microsoft.Extensions.ObjectPool", "6.0.0.0" }, { "Microsoft.Extensions.Options", "5.0.0.0" }, { "Microsoft.Extensions.Options.ConfigurationExtensions", "5.0.0.0" }, { "Microsoft.Extensions.Options.DataAnnotations", "5.0.0.0" }, { "Microsoft.Extensions.Primitives", "5.0.0.0" }, - { "Microsoft.Extensions.WebEncoders", "5.0.0.0" }, - { "Microsoft.JSInterop", "5.0.0.0" }, - { "Microsoft.Net.Http.Headers", "5.0.0.0" }, + { "Microsoft.Extensions.WebEncoders", "6.0.0.0" }, + { "Microsoft.JSInterop", "6.0.0.0" }, + { "Microsoft.Net.Http.Headers", "6.0.0.0" }, { "Microsoft.Win32.Registry", "5.0.0.0" }, { "System.Diagnostics.EventLog", "5.0.0.0" }, { "System.IO.Pipelines", "5.0.0.0" }, @@ -292,6 +292,8 @@ static TestData() public static string GetSharedFxVersion() => GetTestDataValue("SharedFxVersion"); + public static string GetDefaultNetCoreTargetFramework() => GetTestDataValue("DefaultNetCoreTargetFramework"); + public static string GetMicrosoftNETCoreAppPackageVersion() => GetTestDataValue("MicrosoftNETCoreAppRuntimeVersion"); public static string GetReferencePackSharedFxVersion() => GetTestDataValue("ReferencePackSharedFxVersion"); diff --git a/src/Grpc/test/InteropTests/InteropTests.cs b/src/Grpc/test/InteropTests/InteropTests.cs index 040ccc939188..8e4437b66f4c 100644 --- a/src/Grpc/test/InteropTests/InteropTests.cs +++ b/src/Grpc/test/InteropTests/InteropTests.cs @@ -29,18 +29,15 @@ public InteropTests(ITestOutputHelper output) public Task EmptyUnary() => InteropTestCase("empty_unary"); [Fact] - [QuarantinedTest] public Task LargeUnary() => InteropTestCase("large_unary"); [Fact] - [QuarantinedTest] public Task ClientStreaming() => InteropTestCase("client_streaming"); [Fact] public Task ServerStreaming() => InteropTestCase("server_streaming"); [Fact] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/22101")] public Task PingPong() => InteropTestCase("ping_pong"); [Fact] @@ -56,7 +53,6 @@ public InteropTests(ITestOutputHelper output) public Task TimeoutOnSleepingServer() => InteropTestCase("timeout_on_sleeping_server"); [Fact] - [QuarantinedTest] public Task CustomMetadata() => InteropTestCase("custom_metadata"); [Fact] @@ -72,15 +68,12 @@ public InteropTests(ITestOutputHelper output) public Task UnimplementedMethod() => InteropTestCase("unimplemented_method"); [Fact] - [QuarantinedTest("Server is getting 'identity' encoding. Will resolve in gRPC project when updated SDK is available.")] public Task ClientCompressedUnary() => InteropTestCase("client_compressed_unary"); [Fact] - [QuarantinedTest("Server is getting 'identity' encoding. Will resolve in gRPC project when updated SDK is available.")] public Task ClientCompressedStreaming() => InteropTestCase("client_compressed_streaming"); [Fact] - [QuarantinedTest] public Task ServerCompressedUnary() => InteropTestCase("server_compressed_unary"); [Fact] diff --git a/src/Grpc/test/testassets/InteropClient/InteropClient.cs b/src/Grpc/test/testassets/InteropClient/InteropClient.cs index 2b5cb6519623..c522f9915e94 100644 --- a/src/Grpc/test/testassets/InteropClient/InteropClient.cs +++ b/src/Grpc/test/testassets/InteropClient/InteropClient.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; @@ -879,8 +880,8 @@ private static Metadata CreateTestMetadata() // Consider providing ca file in a different format and removing method private byte[]? GetBytesFromPem(string pemString, string section) { - var header = string.Format("-----BEGIN {0}-----", section); - var footer = string.Format("-----END {0}-----", section); + var header = string.Format(CultureInfo.InvariantCulture, "-----BEGIN {0}-----", section); + var footer = string.Format(CultureInfo.InvariantCulture, "-----END {0}-----", section); var start = pemString.IndexOf(header, StringComparison.Ordinal); if (start == -1) diff --git a/src/Hosting/Hosting/src/Internal/ConfigureBuilder.cs b/src/Hosting/Hosting/src/Internal/ConfigureBuilder.cs index e391acd0f3e3..0de9cdedf316 100644 --- a/src/Hosting/Hosting/src/Internal/ConfigureBuilder.cs +++ b/src/Hosting/Hosting/src/Internal/ConfigureBuilder.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; @@ -44,6 +45,7 @@ private void Invoke(object instance, IApplicationBuilder builder) catch (Exception ex) { throw new Exception(string.Format( + CultureInfo.InvariantCulture, "Could not resolve a service of type '{0}' for the parameter '{1}' of method '{2}' on type '{3}'.", parameterInfo.ParameterType.FullName, parameterInfo.Name, diff --git a/src/Hosting/Hosting/src/Internal/HostingEventSource.cs b/src/Hosting/Hosting/src/Internal/HostingEventSource.cs index 6fcfa6726060..10420aaa75e6 100644 --- a/src/Hosting/Hosting/src/Internal/HostingEventSource.cs +++ b/src/Hosting/Hosting/src/Internal/HostingEventSource.cs @@ -87,23 +87,23 @@ protected override void OnEventCommand(EventCommandEventArgs command) // This is the convention for initializing counters in the RuntimeEventSource (lazily on the first enable command). // They aren't disabled afterwards... - _requestsPerSecondCounter ??= new IncrementingPollingCounter("requests-per-second", this, () => _totalRequests) + _requestsPerSecondCounter ??= new IncrementingPollingCounter("requests-per-second", this, () => Volatile.Read(ref _totalRequests)) { DisplayName = "Request Rate", DisplayRateTimeScale = TimeSpan.FromSeconds(1) }; - _totalRequestsCounter ??= new PollingCounter("total-requests", this, () => _totalRequests) + _totalRequestsCounter ??= new PollingCounter("total-requests", this, () => Volatile.Read(ref _totalRequests)) { DisplayName = "Total Requests", }; - _currentRequestsCounter ??= new PollingCounter("current-requests", this, () => _currentRequests) + _currentRequestsCounter ??= new PollingCounter("current-requests", this, () => Volatile.Read(ref _currentRequests)) { DisplayName = "Current Requests" }; - _failedRequestsCounter ??= new PollingCounter("failed-requests", this, () => _failedRequests) + _failedRequestsCounter ??= new PollingCounter("failed-requests", this, () => Volatile.Read(ref _failedRequests)) { DisplayName = "Failed Requests" }; diff --git a/src/Hosting/Hosting/src/Internal/StartupLoader.cs b/src/Hosting/Hosting/src/Internal/StartupLoader.cs index 163c94226976..0b5b774a2b8d 100644 --- a/src/Hosting/Hosting/src/Internal/StartupLoader.cs +++ b/src/Hosting/Hosting/src/Internal/StartupLoader.cs @@ -36,7 +36,7 @@ internal class StartupLoader // ConfigureContainer // ConfigureContainerFilter2 // ConfigureContainerFilter1 - // + // // If the Startup class ConfigureServices returns an and there is at least an registered we // throw as the filters can't be applied. public static StartupMethods LoadMethods(IServiceProvider hostingServiceProvider, [DynamicallyAccessedMembers(StartupLinkerOptions.Accessibility)] Type startupType, string environmentName, object instance = null) @@ -228,15 +228,17 @@ public static Type FindStartupType(string startupAssemblyName, string environmen if (string.IsNullOrEmpty(startupAssemblyName)) { throw new ArgumentException( - string.Format("A startup method, startup type or startup assembly is required. If specifying an assembly, '{0}' cannot be null or empty.", - nameof(startupAssemblyName)), - nameof(startupAssemblyName)); + string.Format( + CultureInfo.CurrentCulture, + "A startup method, startup type or startup assembly is required. If specifying an assembly, '{0}' cannot be null or empty.", + nameof(startupAssemblyName)), + nameof(startupAssemblyName)); } var assembly = Assembly.Load(new AssemblyName(startupAssemblyName)); if (assembly == null) { - throw new InvalidOperationException(String.Format("The assembly '{0}' failed to load.", startupAssemblyName)); + throw new InvalidOperationException($"The assembly '{startupAssemblyName}' failed to load."); } var startupNameWithEnv = "Startup" + environmentName; @@ -266,7 +268,9 @@ public static Type FindStartupType(string startupAssemblyName, string environmen if (type == null) { - throw new InvalidOperationException(String.Format("A type named '{0}' or '{1}' could not be found in assembly '{2}'.", + throw new InvalidOperationException(string.Format( + CultureInfo.CurrentCulture, + "A type named '{0}' or '{1}' could not be found in assembly '{2}'.", startupNameWithEnv, startupNameWithoutEnv, startupAssemblyName)); @@ -308,14 +312,14 @@ private static MethodInfo FindMethod([DynamicallyAccessedMembers(StartupLinkerOp var selectedMethods = methods.Where(method => method.Name.Equals(methodNameWithEnv, StringComparison.OrdinalIgnoreCase)).ToList(); if (selectedMethods.Count > 1) { - throw new InvalidOperationException(string.Format("Having multiple overloads of method '{0}' is not supported.", methodNameWithEnv)); + throw new InvalidOperationException($"Having multiple overloads of method '{methodNameWithEnv}' is not supported."); } if (selectedMethods.Count == 0) { selectedMethods = methods.Where(method => method.Name.Equals(methodNameWithNoEnv, StringComparison.OrdinalIgnoreCase)).ToList(); if (selectedMethods.Count > 1) { - throw new InvalidOperationException(string.Format("Having multiple overloads of method '{0}' is not supported.", methodNameWithNoEnv)); + throw new InvalidOperationException($"Having multiple overloads of method '{methodNameWithNoEnv}' is not supported."); } } @@ -324,7 +328,9 @@ private static MethodInfo FindMethod([DynamicallyAccessedMembers(StartupLinkerOp { if (required) { - throw new InvalidOperationException(string.Format("A public method named '{0}' or '{1}' could not be found in the '{2}' type.", + throw new InvalidOperationException(string.Format( + CultureInfo.CurrentCulture, + "A public method named '{0}' or '{1}' could not be found in the '{2}' type.", methodNameWithEnv, methodNameWithNoEnv, startupType.FullName)); @@ -336,7 +342,9 @@ private static MethodInfo FindMethod([DynamicallyAccessedMembers(StartupLinkerOp { if (required) { - throw new InvalidOperationException(string.Format("The '{0}' method in the type '{1}' must have a return type of '{2}'.", + throw new InvalidOperationException(string.Format( + CultureInfo.CurrentCulture, + "The '{0}' method in the type '{1}' must have a return type of '{2}'.", methodInfo.Name, startupType.FullName, returnType.Name)); diff --git a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsFileProvider.cs b/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsFileProvider.cs index 8e2b9a5c082f..5a9d3a58101e 100644 --- a/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsFileProvider.cs +++ b/src/Hosting/Hosting/src/StaticWebAssets/StaticWebAssetsFileProvider.cs @@ -96,7 +96,7 @@ public IChangeToken Watch(string filter) private static string NormalizePath(string path) { path = path.Replace('\\', '/'); - return path.StartsWith("/") ? path : "/" + path; + return path.StartsWith('/') ? path : "/" + path; } private bool StartsWithBasePath(string subpath, out PathString rest) diff --git a/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs b/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs index 8298649bf0f0..dc166044b87e 100644 --- a/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs +++ b/src/Hosting/Hosting/test/HostingApplicationDiagnosticsTests.cs @@ -93,7 +93,7 @@ public void ActivityIsNotCreatedWhenIsEnabledForActivityIsFalse() diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { - eventsFired |= pair.Key.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn"); + eventsFired |= pair.Key.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn", StringComparison.Ordinal); }), (s, o, arg3) => { if (s == "Microsoft.AspNetCore.Hosting.HttpRequestIn") @@ -127,7 +127,7 @@ public void ActivityIsCreatedButNotLoggedWhenIsEnabledForActivityStartIsFalse() diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { - eventsFired |= pair.Key.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn"); + eventsFired |= pair.Key.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn", StringComparison.Ordinal); }), (s, o, arg3) => { if (s == "Microsoft.AspNetCore.Hosting.HttpRequestIn") @@ -257,7 +257,7 @@ public void ActivityIsAvailibleDuringRequest() diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { }), s => { - if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn")) + if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn", StringComparison.Ordinal)) { return true; } @@ -279,7 +279,7 @@ public void ActivityParentIdAndBaggeReadFromHeaders() diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { }), s => { - if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn")) + if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn", StringComparison.Ordinal)) { return true; } @@ -310,7 +310,7 @@ public void ActivityBaggagePreservesItemsOrder() diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { }), s => { - if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn")) + if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn", StringComparison.Ordinal)) { return true; } @@ -347,7 +347,7 @@ public void ActivityBaggageValuesAreUrlDecodedFromHeaders() diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { }), s => { - if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn")) + if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn", StringComparison.Ordinal)) { return true; } @@ -376,7 +376,7 @@ public void ActivityTraceParentAndTraceStateFromHeaders() diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { }), s => { - if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn")) + if (s.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn", StringComparison.Ordinal)) { return true; } diff --git a/src/Hosting/Server.IntegrationTesting/src/Common/DeploymentParameters.cs b/src/Hosting/Server.IntegrationTesting/src/Common/DeploymentParameters.cs index 0e26e772a0fd..74dbe8697527 100644 --- a/src/Hosting/Server.IntegrationTesting/src/Common/DeploymentParameters.cs +++ b/src/Hosting/Server.IntegrationTesting/src/Common/DeploymentParameters.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Reflection; @@ -61,7 +62,7 @@ public DeploymentParameters( if (!Directory.Exists(applicationPath)) { - throw new DirectoryNotFoundException(string.Format("Application path {0} does not exist.", applicationPath)); + throw new DirectoryNotFoundException($"Application path {applicationPath} does not exist."); } ApplicationPath = applicationPath; @@ -187,12 +188,13 @@ public DeploymentParameters(DeploymentParameters parameters) public override string ToString() { return string.Format( - "[Variation] :: ServerType={0}, Runtime={1}, Arch={2}, BaseUrlHint={3}, Publish={4}", - ServerType, - RuntimeFlavor, - RuntimeArchitecture, - ApplicationBaseUriHint, - PublishApplicationBeforeDeployment); + CultureInfo.InvariantCulture, + "[Variation] :: ServerType={0}, Runtime={1}, Arch={2}, BaseUrlHint={3}, Publish={4}", + ServerType, + RuntimeFlavor, + RuntimeArchitecture, + ApplicationBaseUriHint, + PublishApplicationBeforeDeployment); } } } diff --git a/src/Hosting/Server.IntegrationTesting/src/Common/DotNetCommands.cs b/src/Hosting/Server.IntegrationTesting/src/Common/DotNetCommands.cs index 1bc54b4d555d..e6d4924076f3 100644 --- a/src/Hosting/Server.IntegrationTesting/src/Common/DotNetCommands.cs +++ b/src/Hosting/Server.IntegrationTesting/src/Common/DotNetCommands.cs @@ -33,7 +33,7 @@ public static string GetDotNetHome() } else if (!string.IsNullOrEmpty(dotnetRoot)) { - if (dotnetRoot.EndsWith("x64")) + if (dotnetRoot.EndsWith("x64", StringComparison.Ordinal)) { // DOTNET_ROOT has x64 appended to the path, which we append again in GetDotNetInstallDir result = dotnetRoot[0..^3]; diff --git a/src/Hosting/Server.IntegrationTesting/src/Deployers/ApplicationDeployer.cs b/src/Hosting/Server.IntegrationTesting/src/Deployers/ApplicationDeployer.cs index c6464a9833b4..5aa7c1190840 100644 --- a/src/Hosting/Server.IntegrationTesting/src/Deployers/ApplicationDeployer.cs +++ b/src/Hosting/Server.IntegrationTesting/src/Deployers/ApplicationDeployer.cs @@ -54,7 +54,7 @@ private void ValidateParameters() if (!Directory.Exists(DeploymentParameters.ApplicationPath)) { - throw new DirectoryNotFoundException(string.Format("Application path {0} does not exist.", DeploymentParameters.ApplicationPath)); + throw new DirectoryNotFoundException($"Application path {DeploymentParameters.ApplicationPath} does not exist."); } if (string.IsNullOrEmpty(DeploymentParameters.ApplicationName)) diff --git a/src/Hosting/Server.IntegrationTesting/src/Deployers/ApplicationDeployerFactory.cs b/src/Hosting/Server.IntegrationTesting/src/Deployers/ApplicationDeployerFactory.cs index 959f4ffeedec..8d5799faf040 100644 --- a/src/Hosting/Server.IntegrationTesting/src/Deployers/ApplicationDeployerFactory.cs +++ b/src/Hosting/Server.IntegrationTesting/src/Deployers/ApplicationDeployerFactory.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Server.IntegrationTesting @@ -41,8 +42,10 @@ public static ApplicationDeployer Create(DeploymentParameters deploymentParamete return new NginxDeployer(deploymentParameters, loggerFactory); default: throw new NotSupportedException( - string.Format("Found no deployers suitable for server type '{0}' with the current runtime.", - deploymentParameters.ServerType) + string.Format( + CultureInfo.CurrentCulture, + "Found no deployers suitable for server type '{0}' with the current runtime.", + deploymentParameters.ServerType) ); } } diff --git a/src/Hosting/Server.IntegrationTesting/src/Deployers/NginxDeployer.cs b/src/Hosting/Server.IntegrationTesting/src/Deployers/NginxDeployer.cs index 262ff80ce89d..90eff1c833df 100644 --- a/src/Hosting/Server.IntegrationTesting/src/Deployers/NginxDeployer.cs +++ b/src/Hosting/Server.IntegrationTesting/src/Deployers/NginxDeployer.cs @@ -1,8 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Net; using System.Net.Http; @@ -144,7 +145,7 @@ private void SetupNginx(string redirectUri, Uri originalUri) .Replace("[user]", userName) .Replace("[errorlog]", errorLog) .Replace("[accesslog]", accessLog) - .Replace("[listenPort]", originalUri.Port.ToString() + (_portSelector != null ? " reuseport" : "")) + .Replace("[listenPort]", originalUri.Port.ToString(CultureInfo.InvariantCulture) + (_portSelector != null ? " reuseport" : "")) .Replace("[redirectUri]", redirectUri) .Replace("[pidFile]", pidFile); Logger.LogDebug("Using PID file: {pidFile}", pidFile); diff --git a/src/Hosting/Server.IntegrationTesting/src/xunit/SkipIfEnvironmentVariableNotEnabled.cs b/src/Hosting/Server.IntegrationTesting/src/xunit/SkipIfEnvironmentVariableNotEnabled.cs index caed568f639a..dad8ea3037c8 100644 --- a/src/Hosting/Server.IntegrationTesting/src/xunit/SkipIfEnvironmentVariableNotEnabled.cs +++ b/src/Hosting/Server.IntegrationTesting/src/xunit/SkipIfEnvironmentVariableNotEnabled.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -24,7 +24,7 @@ public bool IsMet { get { - return string.Compare(Environment.GetEnvironmentVariable(_environmentVariableName), "true", ignoreCase: true) == 0; + return string.Equals(Environment.GetEnvironmentVariable(_environmentVariableName), "true", StringComparison.OrdinalIgnoreCase); } } @@ -38,4 +38,4 @@ public string SkipReason public string AdditionalInfo { get; set; } } -} \ No newline at end of file +} diff --git a/src/Hosting/TestHost/src/ClientHandler.cs b/src/Hosting/TestHost/src/ClientHandler.cs index 0b8cc69dc289..e31d80e36921 100644 --- a/src/Hosting/TestHost/src/ClientHandler.cs +++ b/src/Hosting/TestHost/src/ClientHandler.cs @@ -37,7 +37,7 @@ internal ClientHandler(PathString pathBase, ApplicationWrapper application) _application = application ?? throw new ArgumentNullException(nameof(application)); // PathString.StartsWithSegments that we use below requires the base path to not end in a slash. - if (pathBase.HasValue && pathBase.Value.EndsWith("/")) + if (pathBase.HasValue && pathBase.Value.EndsWith('/')) { pathBase = new PathString(pathBase.Value[..^1]); // All but the last character } diff --git a/src/Hosting/TestHost/src/TestServer.cs b/src/Hosting/TestHost/src/TestServer.cs index 1ba0471c74c4..275a73b69ecb 100644 --- a/src/Hosting/TestHost/src/TestServer.cs +++ b/src/Hosting/TestHost/src/TestServer.cs @@ -172,7 +172,7 @@ public async Task SendAsync(Action configureContext, C request.Host = new HostString(request.Host.Host); } var pathBase = PathString.FromUriComponent(BaseAddress); - if (pathBase.HasValue && pathBase.Value.EndsWith("/")) + if (pathBase.HasValue && pathBase.Value.EndsWith('/')) { pathBase = new PathString(pathBase.Value[..^1]); // All but the last character. } diff --git a/src/Hosting/TestHost/src/WebSocketClient.cs b/src/Hosting/TestHost/src/WebSocketClient.cs index 1d9b5df6463a..ea3fb80ae904 100644 --- a/src/Hosting/TestHost/src/WebSocketClient.cs +++ b/src/Hosting/TestHost/src/WebSocketClient.cs @@ -28,7 +28,7 @@ internal WebSocketClient(PathString pathBase, ApplicationWrapper application) _application = application ?? throw new ArgumentNullException(nameof(application)); // PathString.StartsWithSegments that we use below requires the base path to not end in a slash. - if (pathBase.HasValue && pathBase.Value.EndsWith("/")) + if (pathBase.HasValue && pathBase.Value.EndsWith('/')) { pathBase = new PathString(pathBase.Value[..^1]); // All but the last character. } diff --git a/src/Hosting/test/FunctionalTests/ShutdownTests.cs b/src/Hosting/test/FunctionalTests/ShutdownTests.cs index ca689f8092f9..1434c21d98ff 100644 --- a/src/Hosting/test/FunctionalTests/ShutdownTests.cs +++ b/src/Hosting/test/FunctionalTests/ShutdownTests.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -73,14 +74,14 @@ private async Task ExecuteShutdownTest(string testName, string shutdownMechanic) { await deployer.DeployAsync(); - var started = new ManualResetEventSlim(); - var completed = new ManualResetEventSlim(); + var startedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var completedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var output = string.Empty; deployer.HostProcess.OutputDataReceived += (sender, args) => { - if (!string.IsNullOrEmpty(args.Data) && args.Data.StartsWith(StartedMessage)) + if (!string.IsNullOrEmpty(args.Data) && args.Data.StartsWith(StartedMessage, StringComparison.Ordinal)) { - started.Set(); + startedTcs.TrySetResult(); output += args.Data.Substring(StartedMessage.Length) + '\n'; } else @@ -90,26 +91,30 @@ private async Task ExecuteShutdownTest(string testName, string shutdownMechanic) if (output.Contains(CompletionMessage)) { - completed.Set(); + completedTcs.TrySetResult(); } }; - started.Wait(50000); - - if (!started.IsSet) + try + { + await startedTcs.Task.TimeoutAfter(TimeSpan.FromMinutes(1)); + } + catch (TimeoutException ex) { - throw new InvalidOperationException("Application did not start successfully"); + throw new InvalidOperationException("Timeout while waiting for host process to output started message.", ex); } SendSIGINT(deployer.HostProcess.Id); WaitForExitOrKill(deployer.HostProcess); - completed.Wait(50000); - - if (!started.IsSet) + try + { + await completedTcs.Task.TimeoutAfter(TimeSpan.FromMinutes(1)); + } + catch (TimeoutException ex) { - throw new InvalidOperationException($"Application did not write the expected output. The received output is: {output}"); + throw new InvalidOperationException($"Timeout while waiting for host process to output completion message. The received output is: {output}", ex); } output = output.Trim('\n'); @@ -124,7 +129,7 @@ private static void SendSIGINT(int processId) var startInfo = new ProcessStartInfo { FileName = "kill", - Arguments = processId.ToString(), + Arguments = processId.ToString(CultureInfo.InvariantCulture), RedirectStandardOutput = true, UseShellExecute = false }; diff --git a/src/Hosting/test/FunctionalTests/WebHostBuilderTests.cs b/src/Hosting/test/FunctionalTests/WebHostBuilderTests.cs index a6735ea9e28d..8e5ebd058ed9 100644 --- a/src/Hosting/test/FunctionalTests/WebHostBuilderTests.cs +++ b/src/Hosting/test/FunctionalTests/WebHostBuilderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -28,7 +29,7 @@ public async Task InjectedStartup_DefaultApplicationNameIsEntryAssembly(TestVari { var logger = loggerFactory.CreateLogger(nameof(InjectedStartup_DefaultApplicationNameIsEntryAssembly)); -// https://github.com/dotnet/aspnetcore/issues/8247 + // https://github.com/dotnet/aspnetcore/issues/8247 #pragma warning disable 0618 var applicationPath = Path.Combine(TestPathUtilities.GetSolutionRootDirectory("Hosting"), "test", "testassets", "IStartupInjectionAssemblyName"); #pragma warning restore 0618 @@ -44,17 +45,24 @@ public async Task InjectedStartup_DefaultApplicationNameIsEntryAssembly(TestVari await deployer.DeployAsync(); string output = string.Empty; - var mre = new ManualResetEventSlim(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); deployer.HostProcess.OutputDataReceived += (sender, args) => { if (!string.IsNullOrWhiteSpace(args.Data)) { output += args.Data + '\n'; - mre.Set(); + tcs.TrySetResult(); } }; - mre.Wait(50000); + try + { + await tcs.Task.TimeoutAfter(TimeSpan.FromMinutes(1)); + } + catch (TimeoutException ex) + { + throw new InvalidOperationException("Timeout while waiting for output from host process.", ex); + } output = output.Trim('\n'); diff --git a/src/Html/Abstractions/test/HtmlContentBuilderExtensionsTest.cs b/src/Html/Abstractions/test/HtmlContentBuilderExtensionsTest.cs index c14daeeebb69..5fc4a8d03b48 100644 --- a/src/Html/Abstractions/test/HtmlContentBuilderExtensionsTest.cs +++ b/src/Html/Abstractions/test/HtmlContentBuilderExtensionsTest.cs @@ -347,7 +347,7 @@ public void Builder_AppendFormat_WithDifferentCurrentCulture() var builder = new TestHtmlContentBuilder(); // Act - builder.AppendFormat(CultureInfo.CurrentCulture, "{0:D}", DateTime.Parse("01/02/2015")); + builder.AppendFormat(CultureInfo.CurrentCulture, "{0:D}", new DateTime(2015, 02, 01)); // Assert Assert.Equal( diff --git a/src/Html/Abstractions/test/HtmlFormattableStringTest.cs b/src/Html/Abstractions/test/HtmlFormattableStringTest.cs index 64e000751ec4..bc4be7c1064c 100644 --- a/src/Html/Abstractions/test/HtmlFormattableStringTest.cs +++ b/src/Html/Abstractions/test/HtmlFormattableStringTest.cs @@ -196,7 +196,7 @@ public void HtmlFormattableString_UsesPassedInCulture() public void HtmlFormattableString_UsesCurrentCulture() { // Arrange - var formattableString = new HtmlFormattableString("{0:D}", DateTime.Parse("01/02/2015")); + var formattableString = new HtmlFormattableString("{0:D}", new DateTime(2015, 02, 01)); // Act var result = HtmlContentToString(formattableString); diff --git a/src/Http/Headers/src/HeaderUtilities.cs b/src/Http/Headers/src/HeaderUtilities.cs index c1e3ad90d42b..cda9cf82b4f2 100644 --- a/src/Http/Headers/src/HeaderUtilities.cs +++ b/src/Http/Headers/src/HeaderUtilities.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Globalization; using Microsoft.Extensions.Primitives; @@ -228,7 +229,7 @@ private static int AdvanceCacheDirectiveIndex(int current, string headerValue) /// . /// // e.g. { "headerValue=10, targetHeaderValue=30" } - public static bool TryParseSeconds(StringValues headerValues, string targetValue, out TimeSpan? value) + public static bool TryParseSeconds(StringValues headerValues, string targetValue, [NotNullWhen(true)] out TimeSpan? value) { if (StringValues.IsNullOrEmpty(headerValues) || string.IsNullOrEmpty(targetValue)) { @@ -597,7 +598,7 @@ public static string FormatDate(DateTimeOffset dateTime, bool quoted) }); } - return dateTime.ToString("r"); + return dateTime.ToString("r", CultureInfo.InvariantCulture); } public static StringSegment RemoveQuotes(StringSegment input) diff --git a/src/Http/Headers/src/MediaTypeHeaderValue.cs b/src/Http/Headers/src/MediaTypeHeaderValue.cs index af2bba6e2207..2ba881539b6a 100644 --- a/src/Http/Headers/src/MediaTypeHeaderValue.cs +++ b/src/Http/Headers/src/MediaTypeHeaderValue.cs @@ -437,6 +437,32 @@ public MediaTypeHeaderValue CopyAsReadOnly() return other; } + /// + /// Gets a value indicating whether is a subset of + /// this in terms of type/subType. A "subset" is defined as the same or a more specific media type + /// according to the precedence described in https://www.ietf.org/rfc/rfc2068.txt section 14.1, Accept. + /// + /// The to compare. + /// + /// A value indicating whether is a subset of + /// this . + /// + /// + /// For example "multipart/mixed" is a subset of "multipart/mixed", + /// "multipart/*", and "*/*" but not "multipart/message." + /// + public bool MatchesMediaType(StringSegment otherMediaType) + { + if (StringSegment.IsNullOrEmpty(otherMediaType)) + { + return false; + } + GetMediaTypeExpressionLength(otherMediaType, 0, out var mediaType); + + return MatchesType(mediaType) && MatchesSubtype(mediaType); + } + + public override string ToString() { var builder = new StringBuilder(); @@ -645,6 +671,14 @@ private bool MatchesType(MediaTypeHeaderValue set) set.Type.Equals(Type, StringComparison.OrdinalIgnoreCase); } + private bool MatchesType(StringSegment mediaType) + { + var type = mediaType.Subsegment(0, mediaType.IndexOf(ForwardSlashCharacter)); + + return MatchesAllTypes || + Type.Equals(type, StringComparison.OrdinalIgnoreCase); + } + private bool MatchesSubtype(MediaTypeHeaderValue set) { if (set.MatchesAllSubTypes) @@ -672,18 +706,79 @@ private bool MatchesSubtype(MediaTypeHeaderValue set) } } + private bool MatchesSubtype(StringSegment mediaType) + { + if (MatchesAllSubTypes) + { + return true; + } + + var subType = mediaType.Subsegment(mediaType.IndexOf(ForwardSlashCharacter) + 1); + + StringSegment suffix; + var startOfSuffix = subType.LastIndexOf(PlusCharacter); + if (startOfSuffix == -1) + { + suffix = default(StringSegment); + } + else + { + suffix = subType.Subsegment(startOfSuffix + 1); + } + + if (Suffix.HasValue) + { + if (suffix.HasValue) + { + return MatchesSubtypeWithoutSuffix(subType, startOfSuffix) && MatchesSubtypeSuffix(suffix); + } + else + { + return false; + } + } + else + { + // If this subtype or suffix matches the subtype of the mediaType, + // it is considered a subtype. + // Ex: application/json > application/val+json + return MatchesEitherSubtypeOrSuffix(subType, suffix); + } + } + private bool MatchesSubtypeWithoutSuffix(MediaTypeHeaderValue set) { return set.MatchesAllSubTypesWithoutSuffix || set.SubTypeWithoutSuffix.Equals(SubTypeWithoutSuffix, StringComparison.OrdinalIgnoreCase); } + private bool MatchesSubtypeWithoutSuffix(StringSegment subType, int startOfSuffix) + { + StringSegment subTypeWithoutSuffix; + if (startOfSuffix == -1) + { + subTypeWithoutSuffix = subType; + } + else + { + subTypeWithoutSuffix = subType.Subsegment(0, startOfSuffix); + } + return SubTypeWithoutSuffix.Equals(WildcardString, StringComparison.OrdinalIgnoreCase) || + SubTypeWithoutSuffix.Equals(subTypeWithoutSuffix, StringComparison.OrdinalIgnoreCase); + } + private bool MatchesEitherSubtypeOrSuffix(MediaTypeHeaderValue set) { return set.SubType.Equals(SubType, StringComparison.OrdinalIgnoreCase) || set.SubType.Equals(Suffix, StringComparison.OrdinalIgnoreCase); } + private bool MatchesEitherSubtypeOrSuffix(StringSegment subType, StringSegment suffix) + { + return subType.Equals(SubType, StringComparison.OrdinalIgnoreCase) || + SubType.Equals(suffix, StringComparison.OrdinalIgnoreCase); + } + private bool MatchesParameters(MediaTypeHeaderValue set) { if (set._parameters != null && set._parameters.Count != 0) @@ -728,5 +823,12 @@ private bool MatchesSubtypeSuffix(MediaTypeHeaderValue set) // because there's no clear use case for it. return set.Suffix.Equals(Suffix, StringComparison.OrdinalIgnoreCase); } + + private bool MatchesSubtypeSuffix(StringSegment suffix) + { + // We don't have support for wildcards on suffixes alone (e.g., "application/entity+*") + // because there's no clear use case for it. + return Suffix.Equals(suffix, StringComparison.OrdinalIgnoreCase); + } } } diff --git a/src/Http/Headers/src/PublicAPI.Unshipped.txt b/src/Http/Headers/src/PublicAPI.Unshipped.txt index d79c9d7fba76..ec721101b5b4 100644 --- a/src/Http/Headers/src/PublicAPI.Unshipped.txt +++ b/src/Http/Headers/src/PublicAPI.Unshipped.txt @@ -94,6 +94,7 @@ Microsoft.Net.Http.Headers.MediaTypeHeaderValue.IsSubsetOf(Microsoft.Net.Http.He Microsoft.Net.Http.Headers.MediaTypeHeaderValue.MatchesAllSubTypes.get -> bool Microsoft.Net.Http.Headers.MediaTypeHeaderValue.MatchesAllSubTypesWithoutSuffix.get -> bool Microsoft.Net.Http.Headers.MediaTypeHeaderValue.MatchesAllTypes.get -> bool +Microsoft.Net.Http.Headers.MediaTypeHeaderValue.MatchesMediaType(Microsoft.Extensions.Primitives.StringSegment otherMediaType) -> bool Microsoft.Net.Http.Headers.MediaTypeHeaderValue.MediaType.get -> Microsoft.Extensions.Primitives.StringSegment Microsoft.Net.Http.Headers.MediaTypeHeaderValue.MediaType.set -> void Microsoft.Net.Http.Headers.MediaTypeHeaderValue.MediaTypeHeaderValue(Microsoft.Extensions.Primitives.StringSegment mediaType) -> void diff --git a/src/Http/Headers/src/SetCookieHeaderValue.cs b/src/Http/Headers/src/SetCookieHeaderValue.cs index 1afee5760fb5..ba6acf5b6fc2 100644 --- a/src/Http/Headers/src/SetCookieHeaderValue.cs +++ b/src/Http/Headers/src/SetCookieHeaderValue.cs @@ -22,9 +22,9 @@ public class SetCookieHeaderValue private const string SecureToken = "secure"; // RFC Draft: https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00 private const string SameSiteToken = "samesite"; - private static readonly string SameSiteNoneToken = SameSiteMode.None.ToString().ToLower(); - private static readonly string SameSiteLaxToken = SameSiteMode.Lax.ToString().ToLower(); - private static readonly string SameSiteStrictToken = SameSiteMode.Strict.ToString().ToLower(); + private static readonly string SameSiteNoneToken = SameSiteMode.None.ToString().ToLowerInvariant(); + private static readonly string SameSiteLaxToken = SameSiteMode.Lax.ToString().ToLowerInvariant(); + private static readonly string SameSiteStrictToken = SameSiteMode.Strict.ToString().ToLowerInvariant(); private const string HttpOnlyToken = "httponly"; private const string SeparatorToken = "; "; diff --git a/src/Http/Headers/test/ContentDispositionHeaderValueTest.cs b/src/Http/Headers/test/ContentDispositionHeaderValueTest.cs index 4d0b1b7cf78f..7fe258e3de9c 100644 --- a/src/Http/Headers/test/ContentDispositionHeaderValueTest.cs +++ b/src/Http/Headers/test/ContentDispositionHeaderValueTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Xunit; @@ -252,7 +253,7 @@ public void SetHttpFileName_ShouldSanitizeFileNameWhereNeeded(string httpFileNam public void Dates_AddDateParameterThenUseProperty_ParametersEntryIsOverwritten() { string validDateString = "\"Tue, 15 Nov 1994 08:12:31 GMT\""; - DateTimeOffset validDate = DateTimeOffset.Parse("Tue, 15 Nov 1994 08:12:31 GMT"); + DateTimeOffset validDate = DateTimeOffset.Parse("Tue, 15 Nov 1994 08:12:31 GMT", CultureInfo.InvariantCulture); var contentDisposition = new ContentDispositionHeaderValue("inline"); diff --git a/src/Http/Headers/test/MediaTypeHeaderValueTest.cs b/src/Http/Headers/test/MediaTypeHeaderValueTest.cs index 025dcab4b1a7..8a67a2dec90d 100644 --- a/src/Http/Headers/test/MediaTypeHeaderValueTest.cs +++ b/src/Http/Headers/test/MediaTypeHeaderValueTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Primitives; +using NuGet.Frameworks; using Xunit; namespace Microsoft.Net.Http.Headers @@ -683,6 +684,115 @@ public void TryParseStrictList_WithSomeInvalidValues_ReturnsFalse() Assert.False(MediaTypeHeaderValue.TryParseStrictList(inputs, out var results)); } + [Theory] + [InlineData("*/*;", "*/*")] + [InlineData("text/*", "text/*")] + [InlineData("text/*", "text/plain")] + [InlineData("*/*;", "text/plain")] + [InlineData("text/plain", "text/plain")] + [InlineData("text/plain;", "text/plain")] + [InlineData("text/plain;", "TEXT/PLAIN")] + public void MatchesMediaType_PositiveCases(string mediaType1, string mediaType2) + { + // Arrange + var parsedMediaType1 = MediaTypeHeaderValue.Parse(mediaType1); + var parsedMediaType2 = MediaTypeHeaderValue.Parse(mediaType2); + + // Act + var matches = parsedMediaType1.MatchesMediaType(mediaType2); + var isSubsetOf = parsedMediaType2.IsSubsetOf(parsedMediaType1); + + // Assert + Assert.True(matches); + //Make sure that MatchesMediaType produces consistent result with IsSubsetOf + Assert.Equal(matches, isSubsetOf); + } + + [Theory] + [InlineData("application/html", "text/*")] + [InlineData("application/json", "application/html")] + [InlineData("text/plain;", "*/*")] + public void MatchesMediaType_NegativeCases(string mediaType1, string mediaType2) + { + // Arrange + var parsedMediaType1 = MediaTypeHeaderValue.Parse(mediaType1); + var parsedMediaType2 = MediaTypeHeaderValue.Parse(mediaType2); + + // Act + var matches = parsedMediaType1.MatchesMediaType(mediaType2); + var isSubsetOf = parsedMediaType2.IsSubsetOf(parsedMediaType1); + + // Assert + Assert.False(matches); + //Make sure that MatchesMediaType produces consistent result with IsSubsetOf + Assert.Equal(matches, isSubsetOf); + } + + [Theory] + [InlineData("application/entity+json", "application/entity+json")] + [InlineData("application/json", "application/entity+json")] + [InlineData("application/*+json", "application/entity+json")] + [InlineData("application/*+json", "application/*+json")] + [InlineData("application/json", "application/problem+json")] + [InlineData("application/json", "application/vnd.restful+json")] + [InlineData("application/*", "application/*+JSON")] + [InlineData("application/*", "application/entity+JSON")] + [InlineData("*/*", "application/entity+json")] + public void MatchesMediaTypeWithSuffixes_PositiveCases(string mediaType1, string mediaType2) + { + // Arrange + var parsedMediaType1 = MediaTypeHeaderValue.Parse(mediaType1); + var parsedMediaType2 = MediaTypeHeaderValue.Parse(mediaType2); + + // Act + var result = parsedMediaType1.MatchesMediaType(mediaType2); + var isSubsetOf = parsedMediaType2.IsSubsetOf(parsedMediaType1); + + // Assert + Assert.True(result); + //Make sure that MatchesMediaType produces consistent result with IsSubsetOf + Assert.Equal(result, isSubsetOf); + } + + [Theory] + [InlineData("application/entity+json", "application/entity+txt")] + [InlineData("application/entity+json", "application/json")] + [InlineData("application/entity+json", "application/entity.v2+json")] + [InlineData("application/*+json", "application/entity+txt")] + [InlineData("application/*+*", "application/json")] + [InlineData("application/entity", "application/entity+")] + [InlineData("application/entity+*", "application/entity+json")] // We don't allow suffixes to be wildcards + [InlineData("application/*+*", "application/entity+json")] // We don't allow suffixes to be wildcards + [InlineData("application/entity+json", "application/entity")] + public void MatchesMediaTypeWithSuffixes_NegativeCases(string mediaType1, string mediaType2) + { + // Arrange + var parsedMediaType1 = MediaTypeHeaderValue.Parse(mediaType1); + var parsedMediaType2 = MediaTypeHeaderValue.Parse(mediaType2); + + // Arrange + var result = parsedMediaType1.MatchesMediaType(mediaType2); + var isSubsetOf = parsedMediaType2.IsSubsetOf(parsedMediaType1); + + // Assert + Assert.False(result); + //Make sure that MatchesMediaType produces consistent result with IsSubsetOf + Assert.Equal(result, isSubsetOf); + } + + [Fact] + public void MatchesMediaType_IgnoresParameters() + { + // Arrange + var parsedMediaType1 = MediaTypeHeaderValue.Parse("application/json;param=1"); + + // Arrange + var result = parsedMediaType1.MatchesMediaType("application/json;param2=1"); + + // Assert + Assert.True(result); + } + [Theory] [InlineData("*/*;", "*/*")] [InlineData("text/*", "text/*")] diff --git a/src/Http/Http.Abstractions/src/Extensions/UseMiddlewareExtensions.cs b/src/Http/Http.Abstractions/src/Extensions/UseMiddlewareExtensions.cs index 164b601d57f8..a4afef8b157a 100644 --- a/src/Http/Http.Abstractions/src/Extensions/UseMiddlewareExtensions.cs +++ b/src/Http/Http.Abstractions/src/Extensions/UseMiddlewareExtensions.cs @@ -33,7 +33,7 @@ public static class UseMiddlewareExtensions /// The instance. /// The arguments to pass to the middleware type instance's constructor. /// The instance. - public static IApplicationBuilder UseMiddleware<[DynamicallyAccessedMembers(MiddlewareAccessibility)]TMiddleware>(this IApplicationBuilder app, params object[] args) + public static IApplicationBuilder UseMiddleware<[DynamicallyAccessedMembers(MiddlewareAccessibility)]TMiddleware>(this IApplicationBuilder app, params object?[] args) { return app.UseMiddleware(typeof(TMiddleware), args); } @@ -45,7 +45,7 @@ public static class UseMiddlewareExtensions /// The middleware type. /// The arguments to pass to the middleware type instance's constructor. /// The instance. - public static IApplicationBuilder UseMiddleware(this IApplicationBuilder app, [DynamicallyAccessedMembers(MiddlewareAccessibility)] Type middleware, params object[] args) + public static IApplicationBuilder UseMiddleware(this IApplicationBuilder app, [DynamicallyAccessedMembers(MiddlewareAccessibility)] Type middleware, params object?[] args) { if (typeof(IMiddleware).GetTypeInfo().IsAssignableFrom(middleware.GetTypeInfo())) { diff --git a/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt b/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt index 0ea10c72ef1b..b6e7a2ef4c86 100644 --- a/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt +++ b/src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt @@ -340,8 +340,8 @@ static Microsoft.AspNetCore.Builder.MapExtensions.Map(this Microsoft.AspNetCore. static Microsoft.AspNetCore.Builder.MapWhenExtensions.MapWhen(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, System.Func! predicate, System.Action! configuration) -> Microsoft.AspNetCore.Builder.IApplicationBuilder! static Microsoft.AspNetCore.Builder.RunExtensions.Run(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, Microsoft.AspNetCore.Http.RequestDelegate! handler) -> void static Microsoft.AspNetCore.Builder.UseExtensions.Use(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, System.Func!, System.Threading.Tasks.Task!>! middleware) -> Microsoft.AspNetCore.Builder.IApplicationBuilder! -static Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, System.Type! middleware, params object![]! args) -> Microsoft.AspNetCore.Builder.IApplicationBuilder! -static Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, params object![]! args) -> Microsoft.AspNetCore.Builder.IApplicationBuilder! +static Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, System.Type! middleware, params object?[]! args) -> Microsoft.AspNetCore.Builder.IApplicationBuilder! +static Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, params object?[]! args) -> Microsoft.AspNetCore.Builder.IApplicationBuilder! static Microsoft.AspNetCore.Builder.UsePathBaseExtensions.UsePathBase(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, Microsoft.AspNetCore.Http.PathString pathBase) -> Microsoft.AspNetCore.Builder.IApplicationBuilder! static Microsoft.AspNetCore.Builder.UseWhenExtensions.UseWhen(this Microsoft.AspNetCore.Builder.IApplicationBuilder! app, System.Func! predicate, System.Action! configuration) -> Microsoft.AspNetCore.Builder.IApplicationBuilder! static Microsoft.AspNetCore.Http.EndpointHttpContextExtensions.GetEndpoint(this Microsoft.AspNetCore.Http.HttpContext! context) -> Microsoft.AspNetCore.Http.Endpoint? diff --git a/src/Http/Http.Extensions/src/HeaderDictionaryTypeExtensions.cs b/src/Http/Http.Extensions/src/HeaderDictionaryTypeExtensions.cs index 0b0c167aad64..8e9cb63cecc3 100644 --- a/src/Http/Http.Extensions/src/HeaderDictionaryTypeExtensions.cs +++ b/src/Http/Http.Extensions/src/HeaderDictionaryTypeExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Http.Headers; @@ -238,7 +239,9 @@ private static T GetViaReflection(string value) if (method == null) { throw new NotSupportedException(string.Format( - "The given type '{0}' does not have a TryParse method with the required signature 'public static bool TryParse(string, out {0}).", nameof(T))); + CultureInfo.CurrentCulture, + "The given type '{0}' does not have a TryParse method with the required signature 'public static bool TryParse(string, out {0}).", + nameof(T))); } var parameters = new object[] { value, null }; @@ -272,7 +275,9 @@ private static IList GetListViaReflection(StringValues values) if (method == null) { throw new NotSupportedException(string.Format( - "The given type '{0}' does not have a TryParseList method with the required signature 'public static bool TryParseList(IList, out IList<{0}>).", nameof(T))); + CultureInfo.CurrentCulture, + "The given type '{0}' does not have a TryParseList method with the required signature 'public static bool TryParseList(IList, out IList<{0}>).", + nameof(T))); } var parameters = new object[] { values, null }; diff --git a/src/Http/Http/src/Internal/ReferenceReadStream.cs b/src/Http/Http/src/Internal/ReferenceReadStream.cs index cee967d0cc22..c6afdc9dca19 100644 --- a/src/Http/Http/src/Internal/ReferenceReadStream.cs +++ b/src/Http/Http/src/Internal/ReferenceReadStream.cs @@ -61,7 +61,7 @@ public override long Position ThrowIfDisposed(); if (value < 0 || value > Length) { - throw new ArgumentOutOfRangeException(nameof(value), value, "The Position must be within the length of the Stream: " + Length.ToString()); + throw new ArgumentOutOfRangeException(nameof(value), value, $"The Position must be within the length of the Stream: {Length}"); } VerifyPosition(); _position = value; diff --git a/src/Http/Http/test/ResponseCookiesTest.cs b/src/Http/Http/test/ResponseCookiesTest.cs index 2c73a75ec1f3..5acf74b09464 100644 --- a/src/Http/Http/test/ResponseCookiesTest.cs +++ b/src/Http/Http/test/ResponseCookiesTest.cs @@ -137,7 +137,7 @@ public void ProvidesMaxAgeWithCookieOptionsArgumentExpectMaxAgeToBeSet() var cookieHeaderValues = headers[HeaderNames.SetCookie]; Assert.Single(cookieHeaderValues); - Assert.Contains($"max-age={maxAgeTime.TotalSeconds.ToString()}", cookieHeaderValues[0]); + Assert.Contains($"max-age={maxAgeTime.TotalSeconds}", cookieHeaderValues[0]); } [Theory] diff --git a/src/Http/Owin/src/OwinEnvironment.cs b/src/Http/Owin/src/OwinEnvironment.cs index 046022de45dc..938d366bf722 100644 --- a/src/Http/Owin/src/OwinEnvironment.cs +++ b/src/Http/Owin/src/OwinEnvironment.cs @@ -47,19 +47,19 @@ public OwinEnvironment(HttpContext context) _context = context; _entries = new Dictionary() { - { OwinConstants.RequestProtocol, new FeatureMap(feature => feature.Protocol, () => string.Empty, (feature, value) => feature.Protocol = Convert.ToString(value)) }, - { OwinConstants.RequestScheme, new FeatureMap(feature => feature.Scheme, () => string.Empty, (feature, value) => feature.Scheme = Convert.ToString(value)) }, - { OwinConstants.RequestMethod, new FeatureMap(feature => feature.Method, () => string.Empty, (feature, value) => feature.Method = Convert.ToString(value)) }, - { OwinConstants.RequestPathBase, new FeatureMap(feature => feature.PathBase, () => string.Empty, (feature, value) => feature.PathBase = Convert.ToString(value)) }, - { OwinConstants.RequestPath, new FeatureMap(feature => feature.Path, () => string.Empty, (feature, value) => feature.Path = Convert.ToString(value)) }, + { OwinConstants.RequestProtocol, new FeatureMap(feature => feature.Protocol, () => string.Empty, (feature, value) => feature.Protocol = Convert.ToString(value, CultureInfo.InvariantCulture)) }, + { OwinConstants.RequestScheme, new FeatureMap(feature => feature.Scheme, () => string.Empty, (feature, value) => feature.Scheme = Convert.ToString(value, CultureInfo.InvariantCulture)) }, + { OwinConstants.RequestMethod, new FeatureMap(feature => feature.Method, () => string.Empty, (feature, value) => feature.Method = Convert.ToString(value, CultureInfo.InvariantCulture)) }, + { OwinConstants.RequestPathBase, new FeatureMap(feature => feature.PathBase, () => string.Empty, (feature, value) => feature.PathBase = Convert.ToString(value, CultureInfo.InvariantCulture)) }, + { OwinConstants.RequestPath, new FeatureMap(feature => feature.Path, () => string.Empty, (feature, value) => feature.Path = Convert.ToString(value, CultureInfo.InvariantCulture)) }, { OwinConstants.RequestQueryString, new FeatureMap(feature => Utilities.RemoveQuestionMark(feature.QueryString), () => string.Empty, - (feature, value) => feature.QueryString = Utilities.AddQuestionMark(Convert.ToString(value))) }, + (feature, value) => feature.QueryString = Utilities.AddQuestionMark(Convert.ToString(value, CultureInfo.InvariantCulture))) }, { OwinConstants.RequestHeaders, new FeatureMap(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeHeaderDictionary((IDictionary)value)) }, { OwinConstants.RequestBody, new FeatureMap(feature => feature.Body, () => Stream.Null, (feature, value) => feature.Body = (Stream)value) }, { OwinConstants.RequestUser, new FeatureMap(feature => feature.User, () => null, (feature, value) => feature.User = (ClaimsPrincipal)value) }, - { OwinConstants.ResponseStatusCode, new FeatureMap(feature => feature.StatusCode, () => 200, (feature, value) => feature.StatusCode = Convert.ToInt32(value)) }, - { OwinConstants.ResponseReasonPhrase, new FeatureMap(feature => feature.ReasonPhrase, (feature, value) => feature.ReasonPhrase = Convert.ToString(value)) }, + { OwinConstants.ResponseStatusCode, new FeatureMap(feature => feature.StatusCode, () => 200, (feature, value) => feature.StatusCode = Convert.ToInt32(value, CultureInfo.InvariantCulture)) }, + { OwinConstants.ResponseReasonPhrase, new FeatureMap(feature => feature.ReasonPhrase, (feature, value) => feature.ReasonPhrase = Convert.ToString(value, CultureInfo.InvariantCulture)) }, { OwinConstants.ResponseHeaders, new FeatureMap(feature => Utilities.MakeDictionaryStringArray(feature.Headers), (feature, value) => feature.Headers = Utilities.MakeHeaderDictionary((IDictionary)value)) }, { OwinConstants.ResponseBody, new FeatureMap(feature => feature.Stream, () => Stream.Null, (feature, value) => context.Response.Body = (Stream)value) }, // DefaultHttpResponse.Body.Set has built in logic to handle replacing the feature. { OwinConstants.CommonKeys.OnSendingHeaders, new FeatureMap( @@ -81,9 +81,9 @@ public OwinEnvironment(HttpContext context) (feature, value) => feature.RemotePort = Convert.ToInt32(value, CultureInfo.InvariantCulture)) }, { OwinConstants.CommonKeys.LocalIpAddress, new FeatureMap(feature => feature.LocalIpAddress.ToString(), - (feature, value) => feature.LocalIpAddress = IPAddress.Parse(Convert.ToString(value))) }, + (feature, value) => feature.LocalIpAddress = IPAddress.Parse(Convert.ToString(value, CultureInfo.InvariantCulture))) }, { OwinConstants.CommonKeys.RemoteIpAddress, new FeatureMap(feature => feature.RemoteIpAddress.ToString(), - (feature, value) => feature.RemoteIpAddress = IPAddress.Parse(Convert.ToString(value))) }, + (feature, value) => feature.RemoteIpAddress = IPAddress.Parse(Convert.ToString(value, CultureInfo.InvariantCulture))) }, { OwinConstants.SendFiles.SendAsync, new FeatureMap(feature => new SendFileFunc(feature.SendFileAsync)) }, @@ -157,7 +157,7 @@ ICollection IDictionary.Keys { object value; return _entries.Where(pair => pair.Value.TryGet(_context, out value)) - .Select(pair => pair.Key).Concat(_context.Items.Keys.Select(key => Convert.ToString(key))).ToList(); + .Select(pair => pair.Key).Concat(_context.Items.Keys.Select(key => Convert.ToString(key, CultureInfo.InvariantCulture))).ToList(); } } @@ -281,7 +281,7 @@ public IEnumerator> GetEnumerator() } foreach (var entryPair in _context.Items) { - yield return new KeyValuePair(Convert.ToString(entryPair.Key), entryPair.Value); + yield return new KeyValuePair(Convert.ToString(entryPair.Key, CultureInfo.InvariantCulture), entryPair.Value); } } diff --git a/src/Http/Owin/src/OwinFeatureCollection.cs b/src/Http/Owin/src/OwinFeatureCollection.cs index 5f39c765b4b8..9149e0d2d214 100644 --- a/src/Http/Owin/src/OwinFeatureCollection.cs +++ b/src/Http/Owin/src/OwinFeatureCollection.cs @@ -206,13 +206,13 @@ IPAddress IHttpConnectionFeature.LocalIpAddress int IHttpConnectionFeature.RemotePort { - get { return int.Parse(Prop(OwinConstants.CommonKeys.RemotePort)); } + get { return int.Parse(Prop(OwinConstants.CommonKeys.RemotePort), CultureInfo.InvariantCulture); } set { Prop(OwinConstants.CommonKeys.RemotePort, value.ToString(CultureInfo.InvariantCulture)); } } int IHttpConnectionFeature.LocalPort { - get { return int.Parse(Prop(OwinConstants.CommonKeys.LocalPort)); } + get { return int.Parse(Prop(OwinConstants.CommonKeys.LocalPort), CultureInfo.InvariantCulture); } set { Prop(OwinConstants.CommonKeys.LocalPort, value.ToString(CultureInfo.InvariantCulture)); } } diff --git a/src/Http/Routing/src/Constraints/HttpMethodRouteConstraint.cs b/src/Http/Routing/src/Constraints/HttpMethodRouteConstraint.cs index b2ad0eff33a2..696f8084017a 100644 --- a/src/Http/Routing/src/Constraints/HttpMethodRouteConstraint.cs +++ b/src/Http/Routing/src/Constraints/HttpMethodRouteConstraint.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Http; @@ -81,7 +82,7 @@ public virtual bool Match( return true; } - return AllowedMethods.Contains(Convert.ToString(obj), StringComparer.OrdinalIgnoreCase); + return AllowedMethods.Contains(Convert.ToString(obj, CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase); default: throw new ArgumentOutOfRangeException(nameof(routeDirection)); diff --git a/src/Http/Routing/src/Matching/HostMatcherPolicy.cs b/src/Http/Routing/src/Matching/HostMatcherPolicy.cs index 842670f9ddf2..e79715bd7ad3 100644 --- a/src/Http/Routing/src/Matching/HostMatcherPolicy.cs +++ b/src/Http/Routing/src/Matching/HostMatcherPolicy.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -471,7 +472,7 @@ public override bool Equals(object? obj) public override string ToString() { - return $"{Host}:{Port?.ToString() ?? WildcardHost}"; + return $"{Host}:{Port?.ToString(CultureInfo.InvariantCulture) ?? WildcardHost}"; } } } diff --git a/src/Http/Routing/src/Matching/HttpMethodMatcherPolicy.cs b/src/Http/Routing/src/Matching/HttpMethodMatcherPolicy.cs index 9ffa13fa91fa..2560e2408a23 100644 --- a/src/Http/Routing/src/Matching/HttpMethodMatcherPolicy.cs +++ b/src/Http/Routing/src/Matching/HttpMethodMatcherPolicy.cs @@ -484,7 +484,7 @@ public EdgeKey(string httpMethod, bool isCorsPreflightRequest) // These are comparable so they can be sorted in tests. public int CompareTo(EdgeKey other) { - var compare = HttpMethod.CompareTo(other.HttpMethod); + var compare = string.Compare(HttpMethod, other.HttpMethod, StringComparison.Ordinal); if (compare != 0) { return compare; diff --git a/src/Http/Routing/src/Patterns/RoutePatternParser.cs b/src/Http/Routing/src/Patterns/RoutePatternParser.cs index 8b8f181f52c1..d59f6779cfe6 100644 --- a/src/Http/Routing/src/Patterns/RoutePatternParser.cs +++ b/src/Http/Routing/src/Patterns/RoutePatternParser.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; namespace Microsoft.AspNetCore.Routing.Patterns { @@ -180,7 +181,7 @@ private static bool ParseParameter(Context context, List parts } else if (context.Current == CloseBrace) { - // When we encounter Closed brace here, it either means end of the parameter or it is a closed + // When we encounter Closed brace here, it either means end of the parameter or it is a closed // brace in the parameter, in that case it needs to be escaped. // Example: {p1:regex(([}}])\w+}. First pair is escaped one and last marks end of the parameter if (!context.MoveNext()) @@ -357,8 +358,8 @@ private static bool IsSegmentValid(Context context, List parts } } - // if a segment has multiple parts, then only the last one parameter can be optional - // if it is following a optional seperator. + // if a segment has multiple parts, then only the last one parameter can be optional + // if it is following a optional seperator. for (var i = 0; i < parts.Count; i++) { var part = parts[i]; @@ -376,8 +377,7 @@ private static bool IsSegmentValid(Context context, List parts // Example of error message: // "In the segment '{RouteValue}{param?}', the optional parameter 'param' is preceded // by an invalid segment '{RouteValue}'. Only a period (.) can precede an optional parameter. - context.Error = string.Format( - Resources.TemplateRoute_OptionalParameterCanbBePrecededByPeriod, + context.Error = Resources.FormatTemplateRoute_OptionalParameterCanbBePrecededByPeriod( RoutePatternPathSegment.DebuggerToString(parts), parameter.Name, parts[i - 1].DebuggerToString()); @@ -390,8 +390,7 @@ private static bool IsSegmentValid(Context context, List parts // Example of error message: // "In the segment '{RouteValue}-{param?}', the optional parameter 'param' is preceded // by an invalid segment '-'. Only a period (.) can precede an optional parameter. - context.Error = string.Format( - Resources.TemplateRoute_OptionalParameterCanbBePrecededByPeriod, + context.Error = Resources.FormatTemplateRoute_OptionalParameterCanbBePrecededByPeriod( RoutePatternPathSegment.DebuggerToString(parts), parameter.Name, parts[i - 1].DebuggerToString()); @@ -405,10 +404,9 @@ private static bool IsSegmentValid(Context context, List parts { // This optional parameter is not the last one in the segment // Example: - // An optional parameter must be at the end of the segment. In the segment '{RouteValue?})', + // An optional parameter must be at the end of the segment. In the segment '{RouteValue?})', // optional parameter 'RouteValue' is followed by ')' - context.Error = string.Format( - Resources.TemplateRoute_OptionalParameterHasTobeTheLast, + context.Error = Resources.FormatTemplateRoute_OptionalParameterHasTobeTheLast( RoutePatternPathSegment.DebuggerToString(parts), parameter.Name, parts[i + 1].DebuggerToString()); diff --git a/src/Http/Routing/src/Tree/UrlMatchingTree.cs b/src/Http/Routing/src/Tree/UrlMatchingTree.cs index 3dec2b54bd21..0798f70da878 100644 --- a/src/Http/Routing/src/Tree/UrlMatchingTree.cs +++ b/src/Http/Routing/src/Tree/UrlMatchingTree.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -158,7 +159,7 @@ internal void AddEntry(InboundRouteEntry entry) current.Matches.Sort((x, y) => { var result = x.Entry.Precedence.CompareTo(y.Entry.Precedence); - return result == 0 ? x.Entry.RouteTemplate.TemplateText!.CompareTo(y.Entry.RouteTemplate.TemplateText) : result; + return result == 0 ? string.Compare(x.Entry.RouteTemplate.TemplateText, y.Entry.RouteTemplate.TemplateText, StringComparison.Ordinal) : result; }); } diff --git a/src/Http/Routing/src/UriBuildingContext.cs b/src/Http/Routing/src/UriBuildingContext.cs index 5bc974d5465d..f5089018006c 100644 --- a/src/Http/Routing/src/UriBuildingContext.cs +++ b/src/Http/Routing/src/UriBuildingContext.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Text; using System.Text.Encodings.Web; @@ -319,7 +320,7 @@ internal void EncodeValue(string value, int start, int characterCount, bool enco private string DebuggerToString() { - return string.Format("{{Accepted: '{0}' Buffered: '{1}'}}", _path, string.Join("", _buffer)); + return string.Format(CultureInfo.InvariantCulture, "{{Accepted: '{0}' Buffered: '{1}'}}", _path, string.Join("", _buffer)); } private readonly struct BufferValue diff --git a/src/Http/Routing/test/UnitTests/TestObjects/SlugifyParameterTransformer.cs b/src/Http/Routing/test/UnitTests/TestObjects/SlugifyParameterTransformer.cs index 625a5c313766..5b3a80086120 100644 --- a/src/Http/Routing/test/UnitTests/TestObjects/SlugifyParameterTransformer.cs +++ b/src/Http/Routing/test/UnitTests/TestObjects/SlugifyParameterTransformer.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Text.RegularExpressions; @@ -10,7 +10,7 @@ public class SlugifyParameterTransformer : IOutboundParameterTransformer public string TransformOutbound(object value) { // Slugify value - return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower(); + return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLowerInvariant(); } } } diff --git a/src/Http/Routing/test/UnitTests/Tree/TreeRouterTest.cs b/src/Http/Routing/test/UnitTests/Tree/TreeRouterTest.cs index 0f9a2a7feb2b..517abedaad93 100644 --- a/src/Http/Routing/test/UnitTests/Tree/TreeRouterTest.cs +++ b/src/Http/Routing/test/UnitTests/Tree/TreeRouterTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -2059,7 +2060,7 @@ private static OutboundRouteEntry MapOutboundEntry( private static string CreateRouteGroup(int order, string template) { - return string.Format("{0}&{1}", order, template); + return string.Format(CultureInfo.InvariantCulture, "{0}&{1}", order, template); } private static DefaultInlineConstraintResolver CreateConstraintResolver() diff --git a/src/Http/Routing/test/testassets/Benchmarks/Program.cs b/src/Http/Routing/test/testassets/Benchmarks/Program.cs index b4b29acb0304..49f9b41ee246 100644 --- a/src/Http/Routing/test/testassets/Benchmarks/Program.cs +++ b/src/Http/Routing/test/testassets/Benchmarks/Program.cs @@ -36,7 +36,7 @@ public static IHostBuilder GetHostBuilder(string[] args) .UseConfiguration(config); }); - var scenario = config["scenarios"]?.ToLower(); + var scenario = config["scenarios"]?.ToLowerInvariant(); if (scenario == "plaintextdispatcher" || scenario == "plaintextendpointrouting") { hostBuilder.ConfigureWebHost(webHostBuilder => diff --git a/src/Http/Routing/test/testassets/RoutingSandbox/SlugifyParameterTransformer.cs b/src/Http/Routing/test/testassets/RoutingSandbox/SlugifyParameterTransformer.cs index 4838fcc89eaf..3eb0c89e7375 100644 --- a/src/Http/Routing/test/testassets/RoutingSandbox/SlugifyParameterTransformer.cs +++ b/src/Http/Routing/test/testassets/RoutingSandbox/SlugifyParameterTransformer.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Text.RegularExpressions; using Microsoft.AspNetCore.Routing; @@ -12,7 +13,7 @@ public class SlugifyParameterTransformer : IOutboundParameterTransformer public string TransformOutbound(object value) { // Slugify value - return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2", RegexOptions.None, TimeSpan.FromMilliseconds(100)).ToLower(); + return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2", RegexOptions.None, TimeSpan.FromMilliseconds(100)).ToLowerInvariant(); } } } diff --git a/src/Http/Routing/tools/Swaggatherer/SwaggathererApplication.cs b/src/Http/Routing/tools/Swaggatherer/SwaggathererApplication.cs index 5cebbf96a22a..06cecdc14b72 100644 --- a/src/Http/Routing/tools/Swaggatherer/SwaggathererApplication.cs +++ b/src/Http/Routing/tools/Swaggatherer/SwaggathererApplication.cs @@ -199,7 +199,7 @@ private bool IsDuplicateTemplate(RouteEntry entry, List others) break; } - if (HttpMethods.HasValue() && + if (HttpMethods.HasValue() && !string.Equals(entry.Method, other.Method, StringComparison.OrdinalIgnoreCase)) { isSame = false; @@ -227,7 +227,7 @@ private static void Sort(List entries) return comparison; } - return x.Template.TemplateText.CompareTo(y.Template.TemplateText); + return string.Compare(x.Template.TemplateText, y.Template.TemplateText, StringComparison.Ordinal); }); } diff --git a/src/Http/Routing/tools/Swaggatherer/Template.cs b/src/Http/Routing/tools/Swaggatherer/Template.cs index 955ec658b194..cce5de2062dc 100644 --- a/src/Http/Routing/tools/Swaggatherer/Template.cs +++ b/src/Http/Routing/tools/Swaggatherer/Template.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; namespace Swaggatherer { @@ -61,7 +62,9 @@ public static string Execute(IReadOnlyList entries) setupMatcherLines.Add($" builder.AddEndpoint(Endpoints[{i}]);"); } - return string.Format(@" + return string.Format( + CultureInfo.InvariantCulture, + @" // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. @@ -118,10 +121,10 @@ private RouteEndpoint CreateEndpoint(string template, string controllerName, str }} return CreateEndpoint( - template, - defaults: defaults, - requiredValues: requiredValues, - metadata: metadata, + template, + defaults: defaults, + requiredValues: requiredValues, + metadata: metadata, routeName: controllerName); }} }} diff --git a/src/Http/WebUtilities/src/BufferedReadStream.cs b/src/Http/WebUtilities/src/BufferedReadStream.cs index 10f1465f3a2e..f34c31e51edf 100644 --- a/src/Http/WebUtilities/src/BufferedReadStream.cs +++ b/src/Http/WebUtilities/src/BufferedReadStream.cs @@ -277,7 +277,7 @@ public bool EnsureBuffered(int minCount) { if (minCount > _buffer.Length) { - throw new ArgumentOutOfRangeException(nameof(minCount), minCount, "The value must be smaller than the buffer size: " + _buffer.Length.ToString()); + throw new ArgumentOutOfRangeException(nameof(minCount), minCount, "The value must be smaller than the buffer size: " + _buffer.Length); } while (_bufferCount < minCount) { @@ -310,7 +310,7 @@ public async Task EnsureBufferedAsync(int minCount, CancellationToken canc { if (minCount > _buffer.Length) { - throw new ArgumentOutOfRangeException(nameof(minCount), minCount, "The value must be smaller than the buffer size: " + _buffer.Length.ToString()); + throw new ArgumentOutOfRangeException(nameof(minCount), minCount, "The value must be smaller than the buffer size: " + _buffer.Length); } while (_bufferCount < minCount) { diff --git a/src/Identity/ApiAuthorization.IdentityServer/test/Configuration/ConfigureSigningCredentialsTests.cs b/src/Identity/ApiAuthorization.IdentityServer/test/Configuration/ConfigureSigningCredentialsTests.cs index 2ec53f7a53f5..b14fb61d15c2 100644 --- a/src/Identity/ApiAuthorization.IdentityServer/test/Configuration/ConfigureSigningCredentialsTests.cs +++ b/src/Identity/ApiAuthorization.IdentityServer/test/Configuration/ConfigureSigningCredentialsTests.cs @@ -99,7 +99,7 @@ public void Configure_AddsDevelopmentKeyFromConfiguration() } [ConditionalFact] - [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "All.OSX")] public void Configure_LoadsPfxCertificateCredentialFromConfiguration() { // Arrange @@ -129,7 +129,7 @@ public void Configure_LoadsPfxCertificateCredentialFromConfiguration() } [ConditionalFact] - [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "All.OSX")] public void Configure_LoadsCertificateStoreCertificateCredentialFromConfiguration() { try diff --git a/src/Identity/ApiAuthorization.IdentityServer/test/Configuration/SigningKeysLoaderTests.cs b/src/Identity/ApiAuthorization.IdentityServer/test/Configuration/SigningKeysLoaderTests.cs index 893be873abe1..96a3bf74b764 100644 --- a/src/Identity/ApiAuthorization.IdentityServer/test/Configuration/SigningKeysLoaderTests.cs +++ b/src/Identity/ApiAuthorization.IdentityServer/test/Configuration/SigningKeysLoaderTests.cs @@ -59,7 +59,7 @@ public static void LoadFromStoreCert_ThrowsIfThereIsNoCertificateAvailable() } [ConditionalFact] - [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "All.OSX")] public static void LoadFromStoreCert_SkipsCertificatesNotYetValid() { try @@ -82,7 +82,7 @@ public static void LoadFromStoreCert_SkipsCertificatesNotYetValid() } [ConditionalFact] - [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "All.OSX")] public static void LoadFromStoreCert_PrefersCertificatesCloserToExpirationDate() { try @@ -105,7 +105,7 @@ public static void LoadFromStoreCert_PrefersCertificatesCloserToExpirationDate() } [ConditionalFact] - [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/6720", Queues = "All.OSX")] public static void LoadFromStoreCert_SkipsExpiredCertificates() { try diff --git a/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryEFOnlyUsersTest.cs b/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryEFOnlyUsersTest.cs index e2a074f92b0d..4672d4f061f7 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryEFOnlyUsersTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryEFOnlyUsersTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq.Expressions; using Microsoft.AspNetCore.Identity.Test; using Microsoft.EntityFrameworkCore; @@ -32,7 +33,7 @@ protected override IdentityUser CreateTestUser(string namePrefix = "", string em { return new IdentityUser { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -47,6 +48,8 @@ protected override void SetUserPasswordHash(IdentityUser user, string hashedPass protected override Expression> UserNameEqualsPredicate(string userName) => u => u.UserName == userName; +#pragma warning disable CA1310 // Specify StringComparison for correctness protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); +#pragma warning restore CA1310 // Specify StringComparison for correctness } } diff --git a/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryEFUserStoreTest.cs b/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryEFUserStoreTest.cs index 0c5b39779cb0..ac16664e77f9 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryEFUserStoreTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryEFUserStoreTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq.Expressions; using Microsoft.AspNetCore.Identity.Test; using Microsoft.Extensions.DependencyInjection; @@ -37,7 +38,7 @@ protected override IdentityUser CreateTestUser(string namePrefix = "", string em { return new IdentityUser { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -47,7 +48,7 @@ protected override IdentityUser CreateTestUser(string namePrefix = "", string em protected override IdentityRole CreateTestRole(string roleNamePrefix = "", bool useRoleNamePrefixAsRoleName = false) { - var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format("{0}{1}", roleNamePrefix, Guid.NewGuid()); + var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", roleNamePrefix, Guid.NewGuid()); return new IdentityRole(roleName); } @@ -60,8 +61,10 @@ protected override void SetUserPasswordHash(IdentityUser user, string hashedPass protected override Expression> RoleNameEqualsPredicate(string roleName) => r => r.Name == roleName; +#pragma warning disable CA1310 // Specify StringComparison for correctness protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); protected override Expression> RoleNameStartsWithPredicate(string roleName) => r => r.Name.StartsWith(roleName); +#pragma warning restore CA1310 // Specify StringComparison for correctness } } diff --git a/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryStoreWithGenericsTest.cs b/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryStoreWithGenericsTest.cs index 7c6a73b8a613..90750dd002be 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryStoreWithGenericsTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.InMemory.Test/InMemoryStoreWithGenericsTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Data.Common; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Security.Claims; @@ -60,7 +61,7 @@ protected override IdentityUserWithGenerics CreateTestUser(string namePrefix = " { return new IdentityUserWithGenerics { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -70,7 +71,7 @@ protected override IdentityUserWithGenerics CreateTestUser(string namePrefix = " protected override MyIdentityRole CreateTestRole(string roleNamePrefix = "", bool useRoleNamePrefixAsRoleName = false) { - var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format("{0}{1}", roleNamePrefix, Guid.NewGuid()); + var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", roleNamePrefix, Guid.NewGuid()); return new MyIdentityRole(roleName); } @@ -83,9 +84,11 @@ protected override void SetUserPasswordHash(IdentityUserWithGenerics user, strin protected override Expression> RoleNameEqualsPredicate(string roleName) => r => r.Name == roleName; +#pragma warning disable CA1310 // Specify StringComparison for correctness protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); protected override Expression> RoleNameStartsWithPredicate(string roleName) => r => r.Name.StartsWith(roleName); +#pragma warning restore CA1310 // Specify StringComparison for correctness [Fact] public async Task CanAddRemoveUserClaimWithIssuer() diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs index 25136f3f94f9..dfcc50a99eab 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Security.Claims; @@ -36,7 +37,7 @@ protected override TUser CreateTestUser(string namePrefix = "", string email = " { return new TUser { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -46,7 +47,9 @@ protected override TUser CreateTestUser(string namePrefix = "", string email = " protected override Expression> UserNameEqualsPredicate(string userName) => u => u.UserName == userName; +#pragma warning disable CA1310 // Specify StringComparison for correctness protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); +#pragma warning restore CA1310 // Specify StringComparison for correctness private TestUserDbContext CreateContext() { diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs index 09dbe0b9b17e..51802dd42f6e 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Security.Claims; @@ -66,7 +67,7 @@ protected override TUser CreateTestUser(string namePrefix = "", string email = " { return new TUser { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -76,7 +77,7 @@ protected override TUser CreateTestUser(string namePrefix = "", string email = " protected override TRole CreateTestRole(string roleNamePrefix = "", bool useRoleNamePrefixAsRoleName = false) { - var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format("{0}{1}", roleNamePrefix, Guid.NewGuid()); + var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", roleNamePrefix, Guid.NewGuid()); return new TRole() { Name = roleName }; } @@ -84,9 +85,11 @@ protected override TRole CreateTestRole(string roleNamePrefix = "", bool useRole protected override Expression> UserNameEqualsPredicate(string userName) => u => u.UserName == userName; +#pragma warning disable CA1310 // Specify StringComparison for correctness protected override Expression> RoleNameStartsWithPredicate(string roleName) => r => r.Name.StartsWith(roleName); protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); +#pragma warning restore CA1310 // Specify StringComparison for correctness protected virtual TestDbContext CreateContext() { diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreEncryptPersonalDataTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreEncryptPersonalDataTest.cs index 62ec33914117..6f9efbe48f60 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreEncryptPersonalDataTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreEncryptPersonalDataTest.cs @@ -58,7 +58,7 @@ private class SillyEncryptor : ILookupProtector public string Unprotect(string keyId, string data) { var pad = _keyRing[keyId]; - if (!data.StartsWith(pad)) + if (!data.StartsWith(pad, StringComparison.Ordinal)) { throw new InvalidOperationException("Didn't find pad."); } @@ -135,7 +135,7 @@ private bool FindInk(DbConnection conn, string column, string id) if (reader.Read()) { var value = reader.GetString(0); - return value.StartsWith("Default:ink:"); + return value.StartsWith("Default:ink:", StringComparison.Ordinal); } } } @@ -157,7 +157,7 @@ private bool FindTokenInk(DbConnection conn, string id, string loginProvider, st if (reader.Read()) { var value = reader.GetString(0); - return value.StartsWith("Default:ink:"); + return value.StartsWith("Default:ink:", StringComparison.Ordinal); } } } @@ -198,7 +198,7 @@ private async Task CustomPersonalDataPropertiesAreProtected(bool prote var applicationServiceProvider = services.BuildServiceProvider(); using (var scope = applicationServiceProvider.CreateScope()) - { + { var dbContext = scope.ServiceProvider.GetRequiredService(); dbContext.Database.EnsureCreated(); diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs index 022e54b77836..63d9cfda9d36 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; @@ -394,7 +395,7 @@ protected override IdentityUser CreateTestUser(string namePrefix = "", string em { return new IdentityUser { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -404,7 +405,7 @@ protected override IdentityUser CreateTestUser(string namePrefix = "", string em protected override IdentityRole CreateTestRole(string roleNamePrefix = "", bool useRoleNamePrefixAsRoleName = false) { - var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format("{0}{1}", roleNamePrefix, Guid.NewGuid()); + var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", roleNamePrefix, Guid.NewGuid()); return new IdentityRole(roleName); } @@ -417,9 +418,11 @@ protected override void SetUserPasswordHash(IdentityUser user, string hashedPass protected override Expression> RoleNameEqualsPredicate(string roleName) => r => r.Name == roleName; +#pragma warning disable CA1310 // Specify StringComparison for correctness protected override Expression> RoleNameStartsWithPredicate(string roleName) => r => r.Name.StartsWith(roleName); protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); +#pragma warning restore CA1310 // Specify StringComparison for correctness } public class ApplicationUser : IdentityUser { } diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreWithGenericsTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreWithGenericsTest.cs index 8e07a8dc8e2e..ba4329b495bd 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreWithGenericsTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreWithGenericsTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Security.Claims; @@ -50,7 +51,7 @@ protected override IdentityUserWithGenerics CreateTestUser(string namePrefix = " { return new IdentityUserWithGenerics { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -60,7 +61,7 @@ protected override IdentityUserWithGenerics CreateTestUser(string namePrefix = " protected override MyIdentityRole CreateTestRole(string roleNamePrefix = "", bool useRoleNamePrefixAsRoleName = false) { - var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format("{0}{1}", roleNamePrefix, Guid.NewGuid()); + var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", roleNamePrefix, Guid.NewGuid()); return new MyIdentityRole(roleName); } @@ -73,9 +74,11 @@ protected override void SetUserPasswordHash(IdentityUserWithGenerics user, strin protected override Expression> RoleNameEqualsPredicate(string roleName) => r => r.Name == roleName; +#pragma warning disable CA1310 // Specify StringComparison for correctness protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); protected override Expression> RoleNameStartsWithPredicate(string roleName) => r => r.Name.StartsWith(roleName); +#pragma warning restore CA1310 // Specify StringComparison for correctness [Fact] public void AddEntityFrameworkStoresWithInvalidUserThrows() diff --git a/src/Identity/Extensions.Core/src/IdentityResult.cs b/src/Identity/Extensions.Core/src/IdentityResult.cs index 8a525fb54aa7..5315340d9f0a 100644 --- a/src/Identity/Extensions.Core/src/IdentityResult.cs +++ b/src/Identity/Extensions.Core/src/IdentityResult.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.Extensions.Logging; @@ -14,7 +15,7 @@ public class IdentityResult { private static readonly IdentityResult _success = new IdentityResult { Succeeded = true }; private List _errors = new List(); - + /// /// Flag indicating whether if the operation succeeded or not. /// @@ -54,14 +55,14 @@ public static IdentityResult Failed(params IdentityError[] errors) /// /// A string representation of the current object. /// - /// If the operation was successful the ToString() will return "Succeeded" otherwise it returned + /// If the operation was successful the ToString() will return "Succeeded" otherwise it returned /// "Failed : " followed by a comma delimited list of error codes from its collection, if any. /// public override string ToString() { - return Succeeded ? - "Succeeded" : - string.Format("{0} : {1}", "Failed", string.Join(",", Errors.Select(x => x.Code).ToList())); + return Succeeded ? + "Succeeded" : + string.Format(CultureInfo.InvariantCulture, "{0} : {1}", "Failed", string.Join(",", Errors.Select(x => x.Code).ToList())); } } } \ No newline at end of file diff --git a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs index 73d48be2f8ba..9b8fbef7da96 100644 --- a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs +++ b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Security.Claims; @@ -1906,8 +1907,9 @@ public async Task NullableDateTimeOperationTest() Assert.Null(await userMgr.GetLockoutEndDateAsync(user)); // set to a valid value - await userMgr.SetLockoutEndDateAsync(user, DateTimeOffset.Parse("01/01/2014")); - Assert.Equal(DateTimeOffset.Parse("01/01/2014"), await userMgr.GetLockoutEndDateAsync(user)); + var lockoutEndDate = new DateTimeOffset(new DateTime(2014, 01, 01)); + await userMgr.SetLockoutEndDateAsync(user, lockoutEndDate); + Assert.Equal(lockoutEndDate, await userMgr.GetLockoutEndDateAsync(user)); } /// diff --git a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/EnableAuthenticator.cshtml.cs b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/EnableAuthenticator.cshtml.cs index 66cab7ef9b2e..3d3d193e4260 100644 --- a/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/EnableAuthenticator.cshtml.cs +++ b/src/Identity/UI/src/Areas/Identity/Pages/V4/Account/Manage/EnableAuthenticator.cshtml.cs @@ -3,6 +3,7 @@ using System; using System.ComponentModel.DataAnnotations; +using System.Globalization; using System.Linq; using System.Text; using System.Text.Encodings.Web; @@ -195,6 +196,7 @@ private string FormatKey(string unformattedKey) private string GenerateQrCodeUri(string email, string unformattedKey) { return string.Format( + CultureInfo.InvariantCulture, AuthenticatorUriFormat, _urlEncoder.Encode("Microsoft.AspNetCore.Identity.UI"), _urlEncoder.Encode(email), diff --git a/src/Identity/UI/src/Microsoft.AspNetCore.Identity.UI.csproj b/src/Identity/UI/src/Microsoft.AspNetCore.Identity.UI.csproj index 1c054fcbcf84..112434a637e8 100644 --- a/src/Identity/UI/src/Microsoft.AspNetCore.Identity.UI.csproj +++ b/src/Identity/UI/src/Microsoft.AspNetCore.Identity.UI.csproj @@ -43,7 +43,7 @@ - + diff --git a/src/Identity/test/Identity.FunctionalTests/Pages/Account/Manage/EnableAuthenticator.cs b/src/Identity/test/Identity.FunctionalTests/Pages/Account/Manage/EnableAuthenticator.cs index 53003d7c8e2f..4d9d765acc32 100644 --- a/src/Identity/test/Identity.FunctionalTests/Pages/Account/Manage/EnableAuthenticator.cs +++ b/src/Identity/test/Identity.FunctionalTests/Pages/Account/Manage/EnableAuthenticator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Net.Http; using System.Security.Cryptography; using System.Threading.Tasks; @@ -53,7 +54,7 @@ public static string ComputeCode(string key) var unixTimestamp = Convert.ToInt64(Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds)); var timestep = Convert.ToInt64(unixTimestamp / 30); var topt = Rfc6238AuthenticationService.ComputeTotp(hash, (ulong)timestep, modifier: null); - return topt.ToString("D6"); + return topt.ToString("D6", CultureInfo.InvariantCulture); } } } \ No newline at end of file diff --git a/src/Identity/test/Identity.Test/IdentityUIScriptsTest.cs b/src/Identity/test/Identity.Test/IdentityUIScriptsTest.cs index d8b16ff741e6..71712b382bb1 100644 --- a/src/Identity/test/Identity.Test/IdentityUIScriptsTest.cs +++ b/src/Identity/test/Identity.Test/IdentityUIScriptsTest.cs @@ -48,7 +48,7 @@ public async Task IdentityUI_ScriptTags_SubresourceIntegrityCheck(ScriptTag scri private async Task GetShaIntegrity(ScriptTag scriptTag) { - var isSha256 = scriptTag.Integrity.StartsWith("sha256"); + var isSha256 = scriptTag.Integrity.StartsWith("sha256", StringComparison.Ordinal); var prefix = isSha256 ? "sha256" : "sha384"; using (var respStream = await _httpClient.GetStreamAsync(scriptTag.Src)) using (var alg256 = SHA256.Create()) diff --git a/src/Identity/test/Identity.Test/PasswordValidatorTest.cs b/src/Identity/test/Identity.Test/PasswordValidatorTest.cs index 89ac413a44c0..8271f5b608d9 100644 --- a/src/Identity/test/Identity.Test/PasswordValidatorTest.cs +++ b/src/Identity/test/Identity.Test/PasswordValidatorTest.cs @@ -112,7 +112,7 @@ public async Task FailsWithoutRequiredUniqueCharsTests(string input, int uniqueC manager.Options.Password.RequiredLength = 0; manager.Options.Password.RequiredUniqueChars = uniqueChars; IdentityResultAssert.IsFailure(await valid.ValidateAsync(manager, null, input), - String.Format("Passwords must use at least {0} different characters.", uniqueChars)); + $"Passwords must use at least {uniqueChars} different characters."); } [Theory] diff --git a/src/Identity/test/Identity.Test/UserManagerTest.cs b/src/Identity/test/Identity.Test/UserManagerTest.cs index 37cecb047c76..c12a34083f28 100644 --- a/src/Identity/test/Identity.Test/UserManagerTest.cs +++ b/src/Identity/test/Identity.Test/UserManagerTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Security.Claims; using System.Threading; @@ -1779,7 +1780,7 @@ public class TestErrorDescriber : IdentityErrorDescriber public override IdentityError DuplicateEmail(string email) { - return new IdentityError { Code = Code, Description = string.Format(FormatError, email) }; + return new IdentityError { Code = Code, Description = string.Format(CultureInfo.InvariantCulture, FormatError, email) }; } } diff --git a/src/Identity/test/InMemory.Test/InMemoryStoreTest.cs b/src/Identity/test/InMemory.Test/InMemoryStoreTest.cs index 6bb7507d2488..d19fc8a62d71 100644 --- a/src/Identity/test/InMemory.Test/InMemoryStoreTest.cs +++ b/src/Identity/test/InMemory.Test/InMemoryStoreTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq.Expressions; using Microsoft.AspNetCore.Identity.Test; using Microsoft.Extensions.DependencyInjection; @@ -35,7 +36,7 @@ protected override PocoUser CreateTestUser(string namePrefix = "", string email { return new PocoUser { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -45,7 +46,7 @@ protected override PocoUser CreateTestUser(string namePrefix = "", string email protected override PocoRole CreateTestRole(string roleNamePrefix = "", bool useRoleNamePrefixAsRoleName = false) { - var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format("{0}{1}", roleNamePrefix, Guid.NewGuid()); + var roleName = useRoleNamePrefixAsRoleName ? roleNamePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", roleNamePrefix, Guid.NewGuid()); return new PocoRole(roleName); } @@ -53,8 +54,8 @@ protected override PocoRole CreateTestRole(string roleNamePrefix = "", bool useR protected override Expression> RoleNameEqualsPredicate(string roleName) => r => r.Name == roleName; - protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); + protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName, StringComparison.Ordinal); - protected override Expression> RoleNameStartsWithPredicate(string roleName) => r => r.Name.StartsWith(roleName); + protected override Expression> RoleNameStartsWithPredicate(string roleName) => r => r.Name.StartsWith(roleName, StringComparison.Ordinal); } } \ No newline at end of file diff --git a/src/Identity/test/InMemory.Test/InMemoryUserStoreTest.cs b/src/Identity/test/InMemory.Test/InMemoryUserStoreTest.cs index ac7a08caa6dd..1862e66c2855 100644 --- a/src/Identity/test/InMemory.Test/InMemoryUserStoreTest.cs +++ b/src/Identity/test/InMemory.Test/InMemoryUserStoreTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq.Expressions; using Microsoft.AspNetCore.Identity.Test; using Microsoft.Data.Sqlite; @@ -32,7 +33,7 @@ protected override PocoUser CreateTestUser(string namePrefix = "", string email { return new PocoUser { - UserName = useNamePrefixAsUserName ? namePrefix : string.Format("{0}{1}", namePrefix, Guid.NewGuid()), + UserName = useNamePrefixAsUserName ? namePrefix : string.Format(CultureInfo.InvariantCulture, "{0}{1}", namePrefix, Guid.NewGuid()), Email = email, PhoneNumber = phoneNumber, LockoutEnabled = lockoutEnabled, @@ -42,7 +43,7 @@ protected override PocoUser CreateTestUser(string namePrefix = "", string email protected override Expression> UserNameEqualsPredicate(string userName) => u => u.UserName == userName; - protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); + protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName, StringComparison.Ordinal); public class Fixture : IDisposable { diff --git a/src/Identity/test/Shared/ApiConsistencyTestBase.cs b/src/Identity/test/Shared/ApiConsistencyTestBase.cs index 29d75df9bb31..162259c5ef2e 100644 --- a/src/Identity/test/Shared/ApiConsistencyTestBase.cs +++ b/src/Identity/test/Shared/ApiConsistencyTestBase.cs @@ -21,12 +21,12 @@ where type.IsVisible && !type.IsSealed && type.DeclaredConstructors.Any(c => c.IsPublic || c.IsFamily || c.IsFamilyOrAssembly) && type.Namespace != null - && !type.Namespace.EndsWith(".Compiled") + && !type.Namespace.EndsWith(".Compiled", StringComparison.Ordinal) from method in type.DeclaredMethods.Where(m => m.IsPublic && !m.IsStatic) where GetBasestTypeInAssembly(method.DeclaringType) == type - && !(method.IsVirtual && !method.IsFinal) - && !method.Name.StartsWith("get_") - && !method.Name.StartsWith("set_") + && !(method.IsVirtual && !method.IsFinal) + && !method.Name.StartsWith("get_", StringComparison.Ordinal) + && !method.Name.StartsWith("set_", StringComparison.Ordinal) && !method.Name.Equals("Dispose") select type.Name + "." + method.Name) .ToList(); @@ -49,7 +49,7 @@ where typeof(Task).IsAssignableFrom(method.ReturnType) var missingSuffixMethods = asyncMethods - .Where(method => !method.Name.EndsWith("Async")) + .Where(method => !method.Name.EndsWith("Async", StringComparison.Ordinal)) .Select(method => method.DeclaringType.Name + "." + method.Name) .Except(GetAsyncSuffixExceptions()) .ToList(); diff --git a/src/Installers/Debian/Runtime/Debian.Runtime.debproj b/src/Installers/Debian/Runtime/Debian.Runtime.debproj index 70931ff3a4ed..20cdfd1699fe 100644 --- a/src/Installers/Debian/Runtime/Debian.Runtime.debproj +++ b/src/Installers/Debian/Runtime/Debian.Runtime.debproj @@ -8,15 +8,17 @@ $(SharedFrameworkLayoutRoot) - $(RuntimeInstallerBaseName)-$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + $(RuntimeInstallerBaseName)-$(AspNetCoreMajorMinorVersion) $(MicrosoftNETCoreAppRuntimeVersion) $(DotnetRuntimeDependencyVersion.Substring(0, $(DotnetRuntimeDependencyVersion.IndexOf('-'))))~$(DotnetRuntimeDependencyVersion.Substring($([MSBuild]::Add($(DotnetRuntimeDependencyVersion.IndexOf('-')), 1)))) + $(MicrosoftNETCoreAppRuntimeVersion.Split('.')[0]).$(MicrosoftNETCoreAppRuntimeVersion.Split('.')[1]) $(SharedFxProductName) $(SharedFxDescription) + DotnetRuntimeDependencyMajorMinorVersion=$(DotnetRuntimeDependencyMajorMinorVersion); DotnetRuntimeDependencyVersion=$(DotnetRuntimeDependencyVersion); diff --git a/src/Installers/Debian/Runtime/debian_config.json.in b/src/Installers/Debian/Runtime/debian_config.json.in index d9c36fb33d1d..3efa7f5381d3 100644 --- a/src/Installers/Debian/Runtime/debian_config.json.in +++ b/src/Installers/Debian/Runtime/debian_config.json.in @@ -29,7 +29,7 @@ }, "debian_dependencies": { - "dotnet-runtime-${AspNetCoreMajorVersion}.${AspNetCoreMinorVersion}": { + "dotnet-runtime-${DotnetRuntimeDependencyMajorMinorVersion}": { "package_version": "${DotnetRuntimeDependencyVersion}" } } diff --git a/src/Installers/Debian/TargetingPack/Debian.TargetingPack.debproj b/src/Installers/Debian/TargetingPack/Debian.TargetingPack.debproj index 43eba9135887..373149c92fc6 100644 --- a/src/Installers/Debian/TargetingPack/Debian.TargetingPack.debproj +++ b/src/Installers/Debian/TargetingPack/Debian.TargetingPack.debproj @@ -8,18 +8,20 @@ $(TargetingPackLayoutRoot) - $(TargetingPackInstallerBaseName)-$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + $(TargetingPackInstallerBaseName)-$(AspNetCoreMajorMinorVersion) ASP.NET Core Targeting Pack - Provides a default set of APIs for building an ASP.NET Core $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) application. Contains reference assemblies, documentation, and other design-time assets. + Provides a default set of APIs for building an ASP.NET Core $(AspNetCoreMajorMinorVersion) application. Contains reference assemblies, documentation, and other design-time assets. $(MicrosoftNETCoreAppRefPackageVersion) $(DotnetTargetingPackDependencyVersion.Substring(0, $(DotnetTargetingPackDependencyVersion.IndexOf('-'))))~$(DotnetTargetingPackDependencyVersion.Substring($([MSBuild]::Add($(DotnetTargetingPackDependencyVersion.IndexOf('-')), 1)))) + $(MicrosoftNETCoreAppRefPackageVersion.Split('.')[0]).$(MicrosoftNETCoreAppRefPackageVersion.Split('.')[1]) $(SharedFxProductName) $(SharedFxDescription) + DotnetTargetingPackDependencyMajorMinorVersion=$(DotnetTargetingPackDependencyMajorMinorVersion); DotnetTargetingPackDependencyVersion=$(DotnetTargetingPackDependencyVersion); diff --git a/src/Installers/Debian/TargetingPack/debian_config.json.in b/src/Installers/Debian/TargetingPack/debian_config.json.in index 74b38efff5a4..4df3587a0951 100644 --- a/src/Installers/Debian/TargetingPack/debian_config.json.in +++ b/src/Installers/Debian/TargetingPack/debian_config.json.in @@ -29,7 +29,7 @@ }, "debian_dependencies": { - "dotnet-targeting-pack-${AspNetCoreMajorVersion}.${AspNetCoreMinorVersion}": { + "dotnet-targeting-pack-${DotnetTargetingPackDependencyMajorMinorVersion}": { "package_version": "${DotnetTargetingPackDependencyVersion}" } } diff --git a/src/Installers/Rpm/Rpm.Runtime.Common.targets b/src/Installers/Rpm/Rpm.Runtime.Common.targets index dea8c0148d67..c2013eca0f7a 100644 --- a/src/Installers/Rpm/Rpm.Runtime.Common.targets +++ b/src/Installers/Rpm/Rpm.Runtime.Common.targets @@ -4,8 +4,8 @@ - $(RuntimeInstallerBaseName)-$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) - $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion) + $(RuntimeInstallerBaseName)-$(AspNetCoreMajorMinorVersion) + $(AspNetCoreMajorMinorVersion).$(AspNetCorePatchVersion) 1 @@ -15,6 +15,8 @@ $(SharedFxDescription) $(SharedFrameworkLayoutRoot) + + $(MicrosoftNETCoreAppRuntimeVersion.Split('.')[0]).$(MicrosoftNETCoreAppRuntimeVersion.Split('.')[1]) @@ -24,6 +26,6 @@ - + diff --git a/src/Installers/Rpm/TargetingPack/Rpm.TargetingPack.rpmproj b/src/Installers/Rpm/TargetingPack/Rpm.TargetingPack.rpmproj index 38f5fbf78bb6..aa0af5374884 100644 --- a/src/Installers/Rpm/TargetingPack/Rpm.TargetingPack.rpmproj +++ b/src/Installers/Rpm/TargetingPack/Rpm.TargetingPack.rpmproj @@ -8,10 +8,12 @@ - $(TargetingPackInstallerBaseName)-$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + $(TargetingPackInstallerBaseName)-$(AspNetCoreMajorMinorVersion) ASP.NET Core Targeting Pack - Provides a default set of APIs for building an ASP.NET Core $(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) application. Contains reference assemblies, documentation, and other design-time assets. + Provides a default set of APIs for building an ASP.NET Core $(AspNetCoreMajorMinorVersion) application. Contains reference assemblies, documentation, and other design-time assets. + + $(MicrosoftNETCoreAppRefPackageVersion.Split('.')[0]).$(MicrosoftNETCoreAppRefPackageVersion.Split('.')[1]) @@ -21,7 +23,7 @@ - + diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props b/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props index d08b147e4ae5..cf5ef5f48827 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props +++ b/src/Installers/Windows/AspNetCoreModule-Setup/Directory.Build.props @@ -15,7 +15,7 @@ $(BUILD_MINOR) - 1$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(BUILD_MAJOR) + 1$(AspNetCoreMajorMinorVersion).$(BUILD_MAJOR) $(ANCMFolderVersion).0 diff --git a/src/Middleware/SpaServices.Extensions/src/Proxying/ConditionalProxyMiddleware.cs b/src/Middleware/SpaServices.Extensions/src/Proxying/ConditionalProxyMiddleware.cs index 99cc8c4ca85a..d1bb2d36986c 100644 --- a/src/Middleware/SpaServices.Extensions/src/Proxying/ConditionalProxyMiddleware.cs +++ b/src/Middleware/SpaServices.Extensions/src/Proxying/ConditionalProxyMiddleware.cs @@ -30,7 +30,7 @@ public ConditionalProxyMiddleware( Task baseUriTask, IHostApplicationLifetime applicationLifetime) { - if (!pathPrefix.StartsWith("/")) + if (!pathPrefix.StartsWith('/')) { pathPrefix = "/" + pathPrefix; } diff --git a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs b/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs index eb103f03f97d..1a420dad7da8 100644 --- a/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs +++ b/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Text.RegularExpressions; using System.Threading; @@ -79,7 +80,7 @@ private static async Task StartCreateReactAppServerAsync( var envVars = new Dictionary { - { "PORT", portNumber.ToString() }, + { "PORT", portNumber.ToString(CultureInfo.InvariantCulture) }, { "BROWSER", "none" }, // We don't want create-react-app to open its own extra browser window pointing to the internal dev server port }; var scriptRunner = new NodeScriptRunner( diff --git a/src/Middleware/StaticFiles/src/HtmlDirectoryFormatter.cs b/src/Middleware/StaticFiles/src/HtmlDirectoryFormatter.cs index a4d0f4a3c5e4..19b384d2f683 100644 --- a/src/Middleware/StaticFiles/src/HtmlDirectoryFormatter.cs +++ b/src/Middleware/StaticFiles/src/HtmlDirectoryFormatter.cs @@ -63,10 +63,13 @@ public virtual Task GenerateContentAsync(HttpContext context, IEnumerable ", CultureInfo.CurrentUICulture.TwoLetterISOLanguageName); - builder.AppendFormat(@" + builder.AppendFormat( + CultureInfo.InvariantCulture, +@" {0} {1}", HtmlEncode(Resources.HtmlDir_IndexOf), HtmlEncode(requestPath.Value)); @@ -107,18 +110,23 @@ header h1 {
"); - builder.AppendFormat(@" + builder.AppendFormat( + CultureInfo.InvariantCulture, + @"

{0} /", HtmlEncode(Resources.HtmlDir_IndexOf)); string cumulativePath = "/"; foreach (var segment in requestPath.Value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)) { cumulativePath = cumulativePath + segment + "/"; - builder.AppendFormat(@"{1}/", + builder.AppendFormat( + CultureInfo.InvariantCulture, + @"{1}/", HtmlEncode(cumulativePath), HtmlEncode(segment)); } - builder.AppendFormat(CultureInfo.CurrentUICulture, + builder.AppendFormat( + CultureInfo.InvariantCulture, @"

@@ -138,7 +146,9 @@ header h1 { // to the table. try { - builder.AppendFormat(@" + builder.AppendFormat( + CultureInfo.InvariantCulture, + @" @@ -172,7 +182,9 @@ header h1 { // to the table. try { - builder.AppendFormat(@" + builder.AppendFormat( + CultureInfo.InvariantCulture, + @" diff --git a/src/Middleware/StaticFiles/test/UnitTests/CacheHeaderTests.cs b/src/Middleware/StaticFiles/test/UnitTests/CacheHeaderTests.cs index 8f02132ea0fc..321e9c408f9d 100644 --- a/src/Middleware/StaticFiles/test/UnitTests/CacheHeaderTests.cs +++ b/src/Middleware/StaticFiles/test/UnitTests/CacheHeaderTests.cs @@ -357,7 +357,7 @@ public async Task SupportsIfModifiedDateFormats(HttpMethod method) { HttpResponseMessage res2 = await server .CreateRequest("/SubFolder/extra.xml") - .AddHeader("If-Modified-Since", DateTimeOffset.UtcNow.ToString(format)) + .AddHeader("If-Modified-Since", DateTimeOffset.UtcNow.ToString(format, CultureInfo.InvariantCulture)) .SendAsync(method.Method); Assert.Equal(HttpStatusCode.NotModified, res2.StatusCode); diff --git a/src/Middleware/StaticFiles/test/UnitTests/DefaultFilesMiddlewareTests.cs b/src/Middleware/StaticFiles/test/UnitTests/DefaultFilesMiddlewareTests.cs index 16411ea59f5c..239c270677db 100644 --- a/src/Middleware/StaticFiles/test/UnitTests/DefaultFilesMiddlewareTests.cs +++ b/src/Middleware/StaticFiles/test/UnitTests/DefaultFilesMiddlewareTests.cs @@ -184,7 +184,7 @@ private async Task FoundDirectoryWithDefaultFile_PathModified(string baseUrl, st var response = await server.CreateClient().GetAsync(requestUrl); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var requestUrlWithSlash = requestUrl.EndsWith("/") ? requestUrl : requestUrl + "/"; + var requestUrlWithSlash = requestUrl.EndsWith('/') ? requestUrl : requestUrl + "/"; Assert.Equal(requestUrlWithSlash + "default.html", await response.Content.ReadAsStringAsync()); // Should be modified and be valid path to file } } diff --git a/src/Middleware/WebSockets/test/ConformanceTests/AutobahnTests.cs b/src/Middleware/WebSockets/test/ConformanceTests/AutobahnTests.cs index 7e452f17d959..5960ec9cb48d 100644 --- a/src/Middleware/WebSockets/test/ConformanceTests/AutobahnTests.cs +++ b/src/Middleware/WebSockets/test/ConformanceTests/AutobahnTests.cs @@ -65,14 +65,11 @@ public async Task AutobahnTestSuite() await tester.DeployTestAndAddToSpec(ServerType.Kestrel, ssl: true, environment: "ManagedSockets", cancellationToken: cts.Token); // Windows-only WebListener tests - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (IsWindows8OrHigher()) { - if (IsWindows8OrHigher()) - { - // WebListener occasionally gives a non-strict response on 3.2. IIS Express seems to have the same behavior. Wonder if it's related to HttpSys? - // For now, just allow the non-strict response, it's not a failure. - await tester.DeployTestAndAddToSpec(ServerType.HttpSys, ssl: false, environment: "ManagedSockets", cancellationToken: cts.Token); - } + // WebListener occasionally gives a non-strict response on 3.2. IIS Express seems to have the same behavior. Wonder if it's related to HttpSys? + // For now, just allow the non-strict response, it's not a failure. + await tester.DeployTestAndAddToSpec(ServerType.HttpSys, ssl: false, environment: "ManagedSockets", cancellationToken: cts.Token); } result = await tester.Run(cts.Token); @@ -85,23 +82,8 @@ public async Task AutobahnTestSuite() } } - private bool IsWindows8OrHigher() - { - const string WindowsName = "Microsoft Windows "; - const int VersionOffset = 18; + private bool IsWindows8OrHigher() => OperatingSystem.IsWindowsVersionAtLeast(6, 2); - if (RuntimeInformation.OSDescription.StartsWith(WindowsName)) - { - var versionStr = RuntimeInformation.OSDescription.Substring(VersionOffset); - Version version; - if (Version.TryParse(versionStr, out version)) - { - return version.Major > 6 || (version.Major == 6 && version.Minor >= 2); - } - } - - return false; - } private bool IsIISExpress10Installed() { diff --git a/src/Middleware/tools/RazorPageGenerator/Program.cs b/src/Middleware/tools/RazorPageGenerator/Program.cs index 60436a46d617..1e9b08e755d6 100644 --- a/src/Middleware/tools/RazorPageGenerator/Program.cs +++ b/src/Middleware/tools/RazorPageGenerator/Program.cs @@ -193,12 +193,12 @@ private string ProcessFileIncludes() var startIndex = 0; while (startIndex < cshtmlContent.Length) { - startIndex = cshtmlContent.IndexOf(startMatch, startIndex); + startIndex = cshtmlContent.IndexOf(startMatch, startIndex, StringComparison.Ordinal); if (startIndex == -1) { break; } - var endIndex = cshtmlContent.IndexOf(endMatch, startIndex); + var endIndex = cshtmlContent.IndexOf(endMatch, startIndex, StringComparison.Ordinal); if (endIndex == -1) { throw new InvalidOperationException($"Invalid include file format in {_source.PhysicalPath}. Usage example: <%$ include: ErrorPage.js %>"); diff --git a/src/MusicStore/samples/MusicStore/Areas/Admin/Controllers/StoreManagerController.cs b/src/MusicStore/samples/MusicStore/Areas/Admin/Controllers/StoreManagerController.cs index 9a75e4a4ceb7..82010a9911a0 100644 --- a/src/MusicStore/samples/MusicStore/Areas/Admin/Controllers/StoreManagerController.cs +++ b/src/MusicStore/samples/MusicStore/Areas/Admin/Controllers/StoreManagerController.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -194,7 +195,7 @@ public async Task RemoveAlbumConfirmed( private static string GetCacheKey(int id) { - return string.Format("album_{0}", id); + return string.Format(CultureInfo.InvariantCulture, "album_{0}", id); } // NOTE: this is used for end to end testing only @@ -213,7 +214,7 @@ public async Task GetAlbumIdFromName(string albumName) return NotFound(); } - return Content(album.AlbumId.ToString()); + return Content(album.AlbumId.ToString(CultureInfo.InvariantCulture)); } } } \ No newline at end of file diff --git a/src/MusicStore/samples/MusicStore/Controllers/AccountController.cs b/src/MusicStore/samples/MusicStore/Controllers/AccountController.cs index 6551c4f7a3c6..87a9ec42ed9e 100644 --- a/src/MusicStore/samples/MusicStore/Controllers/AccountController.cs +++ b/src/MusicStore/samples/MusicStore/Controllers/AccountController.cs @@ -1,3 +1,5 @@ +using System; +using System.Globalization; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; @@ -236,7 +238,7 @@ await MessageServices.SendEmailAsync(model.Email, "Reset Password", #endif } - ModelState.AddModelError("", string.Format("We could not locate an account with email : {0}", model.Email)); + ModelState.AddModelError("", string.Format(CultureInfo.CurrentCulture, "We could not locate an account with email : {0}", model.Email)); // If we got this far, something failed, redisplay form return View(model); @@ -459,7 +461,7 @@ public async Task LogOff() // TODO: Currently SignInManager.SignOut does not sign out OpenIdc and does not have a way to pass in a specific // AuthType to sign out. var appEnv = HttpContext.RequestServices.GetService(); - if (appEnv.EnvironmentName.StartsWith("OpenIdConnect")) + if (appEnv.EnvironmentName.StartsWith("OpenIdConnect", StringComparison.Ordinal)) { return new SignOutResult("OpenIdConnect", new AuthenticationProperties { diff --git a/src/MusicStore/samples/MusicStore/Controllers/StoreController.cs b/src/MusicStore/samples/MusicStore/Controllers/StoreController.cs index 91b4ca2b0a3e..2d2ad4654ea6 100644 --- a/src/MusicStore/samples/MusicStore/Controllers/StoreController.cs +++ b/src/MusicStore/samples/MusicStore/Controllers/StoreController.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; @@ -36,7 +37,7 @@ public async Task Browse(string genre) { // Retrieve Genre genre and its Associated associated Albums albums from database var genreModel = await DbContext.Genres - .Include(g => g.Albums) + .Include(g => g.Albums) .Where(g => g.Name == genre) .FirstOrDefaultAsync(); @@ -52,7 +53,7 @@ public async Task Details( [FromServices] IMemoryCache cache, int id) { - var cacheKey = string.Format("album_{0}", id); + var cacheKey = string.Format(CultureInfo.InvariantCulture, "album_{0}", id); Album album; if (!cache.TryGetValue(cacheKey, out album)) { diff --git a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Facebook/FacebookMockBackChannelHttpHandler.cs b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Facebook/FacebookMockBackChannelHttpHandler.cs index b0978cfe4767..1143ad2664bf 100644 --- a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Facebook/FacebookMockBackChannelHttpHandler.cs +++ b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Facebook/FacebookMockBackChannelHttpHandler.cs @@ -18,14 +18,14 @@ protected async override Task SendAsync(HttpRequestMessage { var response = new HttpResponseMessage(); - if (request.RequestUri.AbsoluteUri.StartsWith("https://graph.facebook.com/v2.6/oauth/access_token")) + if (request.RequestUri.AbsoluteUri.StartsWith("https://graph.facebook.com/v2.6/oauth/access_token", StringComparison.Ordinal)) { var formData = new FormCollection(await new FormReader(await request.Content.ReadAsStreamAsync()).ReadFormAsync()); if (formData["grant_type"] == "authorization_code") { if (formData["code"] == "ValidCode") { - Helpers.ThrowIfConditionFailed(() => ((string)formData["redirect_uri"]).EndsWith("signin-facebook"), "Redirect URI is not ending with /signin-facebook"); + Helpers.ThrowIfConditionFailed(() => ((string)formData["redirect_uri"]).EndsWith("signin-facebook", StringComparison.Ordinal), "Redirect URI is not ending with /signin-facebook"); Helpers.ThrowIfConditionFailed(() => formData["client_id"] == "[AppId]", "Invalid client Id received"); Helpers.ThrowIfConditionFailed(() => formData["client_secret"] == "[AppSecret]", "Invalid client secret received"); response.Content = new StringContent("{ \"access_token\": \"ValidAccessToken\", \"expires_in\": \"100\" }"); @@ -35,7 +35,7 @@ protected async override Task SendAsync(HttpRequestMessage return response; } } - else if (request.RequestUri.AbsoluteUri.StartsWith("https://graph.facebook.com/v2.6/me")) + else if (request.RequestUri.AbsoluteUri.StartsWith("https://graph.facebook.com/v2.6/me", StringComparison.Ordinal)) { var queryParameters = new QueryCollection(QueryHelpers.ParseQuery(request.RequestUri.Query)); Helpers.ThrowIfConditionFailed(() => queryParameters["appsecret_proof"].Count > 0, "appsecret_proof is empty"); diff --git a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Google/GoogleMockBackChannelHttpHandler.cs b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Google/GoogleMockBackChannelHttpHandler.cs index f5eb4a9eadce..e3824ea436e7 100644 --- a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Google/GoogleMockBackChannelHttpHandler.cs +++ b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Google/GoogleMockBackChannelHttpHandler.cs @@ -18,14 +18,14 @@ protected async override Task SendAsync(HttpRequestMessage { var response = new HttpResponseMessage(); - if (request.RequestUri.AbsoluteUri.StartsWith("https://www.googleapis.com/oauth2/v4/token")) + if (request.RequestUri.AbsoluteUri.StartsWith("https://www.googleapis.com/oauth2/v4/token", StringComparison.Ordinal)) { var formData = new FormCollection(await new FormReader(await request.Content.ReadAsStreamAsync()).ReadFormAsync()); if (formData["grant_type"] == "authorization_code") { if (formData["code"] == "ValidCode") { - if (formData["redirect_uri"].Count > 0 && ((string)formData["redirect_uri"]).EndsWith("signin-google") && + if (formData["redirect_uri"].Count > 0 && ((string)formData["redirect_uri"]).EndsWith("signin-google", StringComparison.Ordinal) && formData["client_id"] == "[ClientId]" && formData["client_secret"] == "[ClientSecret]") { response.Content = new StringContent("{\"access_token\":\"ValidAccessToken\",\"refresh_token\":\"ValidRefreshToken\",\"token_type\":\"Bearer\",\"expires_in\":\"1200\",\"id_token\":\"Token\"}", Encoding.UTF8, "application/json"); @@ -36,7 +36,7 @@ protected async override Task SendAsync(HttpRequestMessage response.StatusCode = (HttpStatusCode)400; return response; } - else if (request.RequestUri.AbsoluteUri.StartsWith("https://www.googleapis.com/plus/v1/people/me")) + else if (request.RequestUri.AbsoluteUri.StartsWith("https://www.googleapis.com/plus/v1/people/me", StringComparison.Ordinal)) { if (request.Headers.Authorization.Parameter == "ValidAccessToken") { diff --git a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/MicrosoftAccount/MicrosoftAccountMockBackChannelHandler.cs b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/MicrosoftAccount/MicrosoftAccountMockBackChannelHandler.cs index 3ebf70a79cf2..f1cfaec70cbe 100644 --- a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/MicrosoftAccount/MicrosoftAccountMockBackChannelHandler.cs +++ b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/MicrosoftAccount/MicrosoftAccountMockBackChannelHandler.cs @@ -18,14 +18,14 @@ protected async override Task SendAsync(HttpRequestMessage { var response = new HttpResponseMessage(); - if (request.RequestUri.AbsoluteUri.StartsWith("https://login.microsoftonline.com/common/oauth2/v2.0/token")) + if (request.RequestUri.AbsoluteUri.StartsWith("https://login.microsoftonline.com/common/oauth2/v2.0/token", StringComparison.Ordinal)) { var formData = new FormCollection(await new FormReader(await request.Content.ReadAsStreamAsync()).ReadFormAsync()); if (formData["grant_type"] == "authorization_code") { if (formData["code"] == "ValidCode") { - if (formData["redirect_uri"].Count > 0 && ((string)formData["redirect_uri"]).EndsWith("signin-microsoft") && + if (formData["redirect_uri"].Count > 0 && ((string)formData["redirect_uri"]).EndsWith("signin-microsoft", StringComparison.Ordinal) && formData["client_id"] == "[ClientId]" && formData["client_secret"] == "[ClientSecret]") { response.Content = new StringContent("{\"token_type\":\"bearer\",\"expires_in\":3600,\"scope\":\"https://graph.microsoft.com/user.read\",\"access_token\":\"ValidAccessToken\",\"refresh_token\":\"ValidRefreshToken\",\"authentication_token\":\"ValidAuthenticationToken\"}"); @@ -37,7 +37,7 @@ protected async override Task SendAsync(HttpRequestMessage response.StatusCode = (HttpStatusCode)400; return response; } - else if (request.RequestUri.AbsoluteUri.StartsWith("https://graph.microsoft.com/v1.0/me")) + else if (request.RequestUri.AbsoluteUri.StartsWith("https://graph.microsoft.com/v1.0/me", StringComparison.Ordinal)) { if (request.Headers.Authorization.Parameter == "ValidAccessToken") { diff --git a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Twitter/TwitterMockBackChannelHttpHandler.cs b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Twitter/TwitterMockBackChannelHttpHandler.cs index 2ae319496977..4942f00a3c7b 100644 --- a/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Twitter/TwitterMockBackChannelHttpHandler.cs +++ b/src/MusicStore/samples/MusicStore/ForTesting/Mocks/Twitter/TwitterMockBackChannelHttpHandler.cs @@ -20,7 +20,7 @@ protected async override Task SendAsync(HttpRequestMessage { var response = new HttpResponseMessage(); - if (request.RequestUri.AbsoluteUri.StartsWith("https://api.twitter.com/oauth/access_token")) + if (request.RequestUri.AbsoluteUri.StartsWith("https://api.twitter.com/oauth/access_token", StringComparison.Ordinal)) { var formData = new FormCollection(await new FormReader(await request.Content.ReadAsStreamAsync()).ReadFormAsync()); if (formData["oauth_verifier"] == "valid_oauth_verifier") @@ -47,7 +47,7 @@ protected async override Task SendAsync(HttpRequestMessage response.StatusCode = (HttpStatusCode)400; return response; } - else if (request.RequestUri.AbsoluteUri.StartsWith("https://api.twitter.com/oauth/request_token")) + else if (request.RequestUri.AbsoluteUri.StartsWith("https://api.twitter.com/oauth/request_token", StringComparison.Ordinal)) { var response_Form_data = new List>() { diff --git a/src/MusicStore/samples/MusicStore/Models/SampleData.cs b/src/MusicStore/samples/MusicStore/Models/SampleData.cs index 9541786e6ff0..37a003e962df 100644 --- a/src/MusicStore/samples/MusicStore/Models/SampleData.cs +++ b/src/MusicStore/samples/MusicStore/Models/SampleData.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; @@ -112,7 +113,7 @@ private static async Task CreateAdminUser(IServiceProvider serviceProvider) { for (int i = 0; i < 100; ++i) { - var email = string.Format("User{0:D3}@example.com", i); + var email = string.Format(CultureInfo.InvariantCulture, "User{0:D3}@example.com", i); var normalUser = await userManager.FindByEmailAsync(email); if (normalUser == null) { diff --git a/src/MusicStore/test/MusicStore.E2ETests/Common/DbUtils.cs b/src/MusicStore/test/MusicStore.E2ETests/Common/DbUtils.cs index 9d6030baddf7..c7dc8b135f25 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/Common/DbUtils.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/Common/DbUtils.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using Microsoft.AspNetCore.Testing; using Microsoft.Data.SqlClient; using Microsoft.Extensions.Logging; @@ -35,7 +36,8 @@ public static void DropDatabase(string databaseName, ILogger logger) conn.Open(); var cmd = conn.CreateCommand(); - cmd.CommandText = string.Format(@"IF EXISTS (SELECT * FROM sys.databases WHERE name = N'{0}') + cmd.CommandText = string.Format(CultureInfo.InvariantCulture, + @"IF EXISTS (SELECT * FROM sys.databases WHERE name = N'{0}') BEGIN ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [{0}]; diff --git a/src/MusicStore/test/MusicStore.E2ETests/Common/HtmlDOMHelper.cs b/src/MusicStore/test/MusicStore.E2ETests/Common/HtmlDOMHelper.cs index b1e3398440eb..24a98a017b9e 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/Common/HtmlDOMHelper.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/Common/HtmlDOMHelper.cs @@ -42,7 +42,7 @@ private static string RetrieveAntiForgeryToken(string htmlContent, string action foreach (XmlAttribute attribute in htmlDocument.DocumentElement.Attributes) { - if (string.Compare(attribute.Name, "action", true) == 0 && attribute.Value.EndsWith(actionLocation, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(attribute.Name, "action", StringComparison.OrdinalIgnoreCase) && attribute.Value.EndsWith(actionLocation, StringComparison.OrdinalIgnoreCase)) { foreach (XmlNode input in htmlDocument.GetElementsByTagName("input")) { diff --git a/src/MusicStore/test/MusicStore.E2ETests/Implementation/FacebookLoginScenarios.cs b/src/MusicStore/test/MusicStore.E2ETests/Implementation/FacebookLoginScenarios.cs index eafc6f1c43b8..90872d07ce8b 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/Implementation/FacebookLoginScenarios.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/Implementation/FacebookLoginScenarios.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -80,7 +81,7 @@ public async Task LoginWithFacebook() await ThrowIfResponseStatusNotOk(response); responseContent = await response.Content.ReadAsStringAsync(); - Assert.Contains(string.Format("Hello {0}!", "AspnetvnextTest@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, "Hello {0}!", "AspnetvnextTest@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); // Verify cookie sent Assert.Contains(IdentityCookieName, GetCookieNames()); @@ -89,7 +90,7 @@ public async Task LoginWithFacebook() _logger.LogInformation("Verifying if the middleware events were fired"); //Check for a non existing item - response = await DoGetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); + response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); //This action requires admin permissions. If events are fired this permission is granted Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); _logger.LogInformation("Middleware events were fired successfully"); diff --git a/src/MusicStore/test/MusicStore.E2ETests/Implementation/GoogleLoginScenarios.cs b/src/MusicStore/test/MusicStore.E2ETests/Implementation/GoogleLoginScenarios.cs index 23861f47f491..ca1d62fc5179 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/Implementation/GoogleLoginScenarios.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/Implementation/GoogleLoginScenarios.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -82,7 +83,7 @@ public async Task LoginWithGoogle() await ThrowIfResponseStatusNotOk(response); responseContent = await response.Content.ReadAsStringAsync(); - Assert.Contains(string.Format("Hello {0}!", "AspnetvnextTest@gmail.com"), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, "Hello {0}!", "AspnetvnextTest@gmail.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); // Verify cookie sent Assert.Contains(IdentityCookieName, GetCookieNames()); @@ -92,7 +93,7 @@ public async Task LoginWithGoogle() _logger.LogInformation("Verifying if the middleware events were fired"); //Check for a non existing item - response = await DoGetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); + response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); //This action requires admin permissions. If events are fired this permission is granted _logger.LogDebug(await response.Content.ReadAsStringAsync()); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); diff --git a/src/MusicStore/test/MusicStore.E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs b/src/MusicStore/test/MusicStore.E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs index bfa754204f75..e69183a1b179 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -58,7 +59,7 @@ public async Task LoginWithMicrosoftAccount() var uri = new Uri(new Uri(_deploymentResult.ApplicationBaseUri), header.Path.ToString()); _httpClientHandler.CookieContainer.Add(uri, new Cookie(header.Name.ToString(), header.Value.ToString())); } - + //Post a message to the MicrosoftAccount middleware response = await DoGetAsync("signin-microsoft?code=ValidCode&state=ValidStateData"); await ThrowIfResponseStatusNotOk(response); @@ -79,7 +80,7 @@ public async Task LoginWithMicrosoftAccount() await ThrowIfResponseStatusNotOk(response); responseContent = await response.Content.ReadAsStringAsync(); - Assert.Contains(string.Format("Hello {0}!", "microsoft@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, "Hello {0}!", "microsoft@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); // Verify cookie sent Assert.Contains(IdentityCookieName, GetCookieNames()); @@ -88,7 +89,7 @@ public async Task LoginWithMicrosoftAccount() _logger.LogInformation("Verifying if the middleware events were fired"); //Check for a non existing item - response = await DoGetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); + response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); //This action requires admin permissions. If events are fired this permission is granted _logger.LogInformation(await response.Content.ReadAsStringAsync()); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); diff --git a/src/MusicStore/test/MusicStore.E2ETests/Implementation/OpenIdConnectLoginScenarios.cs b/src/MusicStore/test/MusicStore.E2ETests/Implementation/OpenIdConnectLoginScenarios.cs index 48092a4f6cf3..573767b2e091 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/Implementation/OpenIdConnectLoginScenarios.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/Implementation/OpenIdConnectLoginScenarios.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -82,7 +83,7 @@ public async Task LoginWithOpenIdConnect() await ThrowIfResponseStatusNotOk(response); responseContent = await response.Content.ReadAsStringAsync(); - Assert.Contains(string.Format("Hello {0}!", "User3@aspnettest.onmicrosoft.com"), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, "Hello {0}!", "User3@aspnettest.onmicrosoft.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); // Verify cookie sent Assert.Contains(IdentityCookieName, GetCookieNames()); @@ -91,7 +92,7 @@ public async Task LoginWithOpenIdConnect() _logger.LogInformation("Verifying if the middleware events were fired"); //Check for a non existing item - response = await DoGetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); + response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); //This action requires admin permissions. If events are fired this permission is granted Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); _logger.LogInformation("Middleware events were fired successfully"); diff --git a/src/MusicStore/test/MusicStore.E2ETests/Implementation/TwitterLoginScenarios.cs b/src/MusicStore/test/MusicStore.E2ETests/Implementation/TwitterLoginScenarios.cs index db83f98a3a43..5e13a179ff9f 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/Implementation/TwitterLoginScenarios.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/Implementation/TwitterLoginScenarios.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -77,7 +78,7 @@ public async Task LoginWithTwitter() await ThrowIfResponseStatusNotOk(response); responseContent = await response.Content.ReadAsStringAsync(); - Assert.Contains(string.Format("Hello {0}!", "twitter@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, "Hello {0}!", "twitter@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); // Verify cookie sent Assert.Contains(IdentityCookieName, GetCookieNames()); @@ -86,7 +87,7 @@ public async Task LoginWithTwitter() _logger.LogInformation("Verifying if the middleware events were fired"); //Check for a non existing item - response = await DoGetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); + response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/GetAlbumIdFromName?albumName={0}", "123")); //This action requires admin permissions. If events are fired this permission is granted Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); _logger.LogInformation("Middleware events were fired successfully"); diff --git a/src/MusicStore/test/MusicStore.E2ETests/Implementation/Validator.cs b/src/MusicStore/test/MusicStore.E2ETests/Implementation/Validator.cs index 07dd1f5bb64f..d057cf9e1d39 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/Implementation/Validator.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/Implementation/Validator.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -183,7 +184,7 @@ public async Task AccessStoreWithPermissions() private string PrefixBaseAddress(string url) { - url = string.Format(url, string.Empty); + url = string.Format(CultureInfo.InvariantCulture, url, string.Empty); return url.Replace("//", "/").Replace("%2F%2F", "%2F").Replace("%2F/", "%2F"); } @@ -264,8 +265,8 @@ public async Task RegisterValidUser() //Account verification Assert.Equal(_deploymentResult.ApplicationBaseUri + "Account/Register", response.RequestMessage.RequestUri.AbsoluteUri); Assert.Contains("For DEMO only: You can click this link to confirm the email:", responseContent, StringComparison.OrdinalIgnoreCase); - var startIndex = responseContent.IndexOf("[[link]]", startIndex); + var startIndex = responseContent.IndexOf("[[link]]", startIndex, StringComparison.Ordinal); var confirmUrl = responseContent.Substring(startIndex, endIndex - startIndex); confirmUrl = WebUtility.HtmlDecode(confirmUrl); response = await DoGetAsync(confirmUrl); @@ -293,7 +294,7 @@ public async Task RegisterExistingUser(string email) var content = new FormUrlEncodedContent(formParameters.ToArray()); response = await DoPostAsync("Account/Register", content); responseContent = await response.Content.ReadAsStringAsync(); - Assert.Contains(string.Format("User name '{0}' is already taken.", email), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, "User name '{0}' is already taken.", email), responseContent, StringComparison.OrdinalIgnoreCase); _logger.LogInformation("Identity threw a valid exception that user '{email}' already exists in the system", email); } @@ -361,7 +362,7 @@ public async Task SignInWithUser(string email, string password) var content = new FormUrlEncodedContent(formParameters.ToArray()); response = await DoPostAsync("Account/Login", content); responseContent = await response.Content.ReadAsStringAsync(); - Assert.Contains(string.Format("Hello {0}!", email), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, "Hello {0}!", email), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); //Verify cookie sent Assert.Contains(IdentityCookieName, GetCookieNames()); @@ -420,13 +421,13 @@ public async Task FetchAlbumIdFromName(string albumName) // Run some CORS validation. _logger.LogInformation("Fetching the album id of '{album}'", albumName); _httpClient.DefaultRequestHeaders.Add("Origin", "http://notpermitteddomain.com"); - var response = await DoGetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)); + var response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)); await ThrowIfResponseStatusNotOk(response); Assert.False(response.Headers.TryGetValues("Access-Control-Allow-Origin", out var values)); _httpClient.DefaultRequestHeaders.Remove("Origin"); _httpClient.DefaultRequestHeaders.Add("Origin", "http://example.com"); - response = await DoGetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)); + response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)); await ThrowIfResponseStatusNotOk(response); Assert.Equal("http://example.com", response.Headers.GetValues("Access-Control-Allow-Origin").First()); _httpClient.DefaultRequestHeaders.Remove("Origin"); @@ -439,12 +440,12 @@ public async Task FetchAlbumIdFromName(string albumName) public async Task VerifyAlbumDetails(string albumId, string albumName) { _logger.LogInformation("Getting details of album with Id '{id}'", albumId); - var response = await DoGetAsync(string.Format("Admin/StoreManager/Details?id={0}", albumId)); + var response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/Details?id={0}", albumId)); await ThrowIfResponseStatusNotOk(response); var responseContent = await response.Content.ReadAsStringAsync(); Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("http://myapp/testurl", responseContent, StringComparison.OrdinalIgnoreCase); - Assert.Contains(PrefixBaseAddress(string.Format("Edit", "{0}", albumId)), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(PrefixBaseAddress(string.Format(CultureInfo.InvariantCulture, "Edit", "{0}", albumId)), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains(PrefixBaseAddress("Back to List"), responseContent, StringComparison.OrdinalIgnoreCase); } @@ -463,7 +464,7 @@ public async Task VerifyStatusCodePages() public async Task GetAlbumDetailsFromStore(string albumId, string albumName) { _logger.LogInformation("Getting details of album with Id '{id}'", albumId); - var response = await DoGetAsync(string.Format("Store/Details/{0}", albumId)); + var response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Store/Details/{0}", albumId)); await ThrowIfResponseStatusNotOk(response); var responseContent = await response.Content.ReadAsStringAsync(); Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase); @@ -472,7 +473,7 @@ public async Task GetAlbumDetailsFromStore(string albumId, string albumName) public async Task AddAlbumToCart(string albumId, string albumName) { _logger.LogInformation("Adding album id '{albumId}' to the cart", albumId); - var response = await DoGetAsync(string.Format("ShoppingCart/AddToCart?id={0}", albumId)); + var response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "ShoppingCart/AddToCart?id={0}", albumId)); await ThrowIfResponseStatusNotOk(response); var responseContent = await response.Content.ReadAsStringAsync(); Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase); @@ -523,7 +524,7 @@ public async Task DeleteAlbum(string albumId, string albumName) await ThrowIfResponseStatusNotOk(response); _logger.LogInformation("Verifying if the album '{album}' is deleted from store", albumName); - response = await DoGetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)); + response = await DoGetAsync(string.Format(CultureInfo.InvariantCulture, "Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); _logger.LogInformation("Album '{album}' with id '{Id}' is successfully deleted from the store.", albumName, albumId); } @@ -535,7 +536,7 @@ private async Task ThrowIfResponseStatusNotOk(HttpResponseMessage response) LogHeaders(response, LogLevel.Information); var content = await response.Content.ReadAsStringAsync(); _logger.LogError("Content: Length={0}\n{1}", content.Length, content); - throw new Exception(string.Format("Received the above response with status code : {0}", response.StatusCode)); + throw new Exception(string.Format(CultureInfo.InvariantCulture, "Received the above response with status code : {0}", response.StatusCode)); } } diff --git a/src/MusicStore/test/MusicStore.E2ETests/SmokeTestsOnNanoServer.cs b/src/MusicStore/test/MusicStore.E2ETests/SmokeTestsOnNanoServer.cs index 5459553cf66f..ff6852202bf7 100644 --- a/src/MusicStore/test/MusicStore.E2ETests/SmokeTestsOnNanoServer.cs +++ b/src/MusicStore/test/MusicStore.E2ETests/SmokeTestsOnNanoServer.cs @@ -78,7 +78,7 @@ public DotnetRuntimeSetupTestFixture() var runNanoServerTests = Environment.GetEnvironmentVariable("RUN_TESTS_ON_NANO"); if (string.IsNullOrWhiteSpace(runNanoServerTests) || string.IsNullOrEmpty(runNanoServerTests) - || runNanoServerTests.ToLower() == "false") + || runNanoServerTests.ToLowerInvariant() == "false") { return; } diff --git a/src/Mvc/Mvc.Analyzers/test/TagHelpersInCodeBlocksAnalyzerTest.cs b/src/Mvc/Mvc.Analyzers/test/TagHelpersInCodeBlocksAnalyzerTest.cs index 44eea09663ed..c5d545cf1dc2 100644 --- a/src/Mvc/Mvc.Analyzers/test/TagHelpersInCodeBlocksAnalyzerTest.cs +++ b/src/Mvc/Mvc.Analyzers/test/TagHelpersInCodeBlocksAnalyzerTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -76,7 +77,7 @@ private async Task VerifyDefault(TestSource testSource) // Assert // We want to ignore C# diagnostics because they'll include diagnostics for not awaiting bits correctly. The purpose of this analyzer is to // improve on those error messages but not remove them. - var filteredDiagnostics = result.Where(diagnostic => diagnostic.Id.StartsWith("MVC")); + var filteredDiagnostics = result.Where(diagnostic => diagnostic.Id.StartsWith("MVC", StringComparison.Ordinal)); Assert.Collection( filteredDiagnostics, diagnostic => diff --git a/src/Mvc/Mvc.Analyzers/test/TopLevelParameterNameAnalyzerTest.cs b/src/Mvc/Mvc.Analyzers/test/TopLevelParameterNameAnalyzerTest.cs index 8868548c4b69..2f82d63b1f06 100644 --- a/src/Mvc/Mvc.Analyzers/test/TopLevelParameterNameAnalyzerTest.cs +++ b/src/Mvc/Mvc.Analyzers/test/TopLevelParameterNameAnalyzerTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -322,7 +323,7 @@ private async Task RunTest(string typeName, string parameterName, [CallerMemberN Assert.Equal(descriptor.Id, diagnostic.Id); Assert.Same(descriptor, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(expectedLocation, diagnostic.Location); - Assert.Equal(string.Format(descriptor.MessageFormat.ToString(), typeName, parameterName), diagnostic.GetMessage()); + Assert.Equal(string.Format(CultureInfo.InvariantCulture, descriptor.MessageFormat.ToString(CultureInfo.InvariantCulture), typeName, parameterName), diagnostic.GetMessage(CultureInfo.InvariantCulture)); }); } } diff --git a/src/Mvc/Mvc.Api.Analyzers/src/SymbolApiConventionMatcher.cs b/src/Mvc/Mvc.Api.Analyzers/src/SymbolApiConventionMatcher.cs index 67143109c5ce..3d3a73721a9d 100644 --- a/src/Mvc/Mvc.Api.Analyzers/src/SymbolApiConventionMatcher.cs +++ b/src/Mvc/Mvc.Api.Analyzers/src/SymbolApiConventionMatcher.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -169,7 +169,7 @@ bool IsNameMatchSuffix() } index++; - if (name[index] != char.ToUpper(conventionName[0])) + if (name[index] != char.ToUpperInvariant(conventionName[0])) { // Verify the first letter from convention is upper case. In this case 'n' from "name" return false; diff --git a/src/Mvc/Mvc.Api.Analyzers/test/ApiConventionAnalyzerIntegrationTest.cs b/src/Mvc/Mvc.Api.Analyzers/test/ApiConventionAnalyzerIntegrationTest.cs index 77c5b0d75169..fbcd56f4bfa4 100644 --- a/src/Mvc/Mvc.Api.Analyzers/test/ApiConventionAnalyzerIntegrationTest.cs +++ b/src/Mvc/Mvc.Api.Analyzers/test/ApiConventionAnalyzerIntegrationTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.AspNetCore.Analyzer.Testing; @@ -176,7 +177,7 @@ private Task RunTest(DiagnosticDescriptor descriptor, [CallerMemberName] string => RunTest(descriptor, Array.Empty(), testMethod); private Task RunTest(DiagnosticDescriptor descriptor, int statusCode, [CallerMemberName] string testMethod = "") - => RunTest(descriptor, new[] { statusCode.ToString() }, testMethod); + => RunTest(descriptor, new[] { statusCode.ToString(CultureInfo.InvariantCulture) }, testMethod); private async Task RunTest(DiagnosticDescriptor descriptor, object[] args, [CallerMemberName] string testMethod = "") { @@ -195,7 +196,7 @@ private async Task RunTest(DiagnosticDescriptor descriptor, object[] args, [Call Assert.Equal(descriptor.Id, diagnostic.Id); Assert.Same(descriptor, diagnostic.Descriptor); AnalyzerAssert.DiagnosticLocation(expectedLocation, diagnostic.Location); - Assert.Equal(string.Format(descriptor.MessageFormat.ToString(), args), diagnostic.GetMessage()); + Assert.Equal(string.Format(CultureInfo.InvariantCulture, descriptor.MessageFormat.ToString(CultureInfo.InvariantCulture), args), diagnostic.GetMessage(CultureInfo.InvariantCulture)); }); } private class ApiConventionWith1006DiagnosticEnabledRunner : MvcDiagnosticAnalyzerRunner diff --git a/src/Mvc/Mvc.Api.Analyzers/test/TestFiles/SymbolApiResponseMetadataProviderTest/GetResponseMetadataTests.cs b/src/Mvc/Mvc.Api.Analyzers/test/TestFiles/SymbolApiResponseMetadataProviderTest/GetResponseMetadataTests.cs index d0728bbef376..bcf250847460 100644 --- a/src/Mvc/Mvc.Api.Analyzers/test/TestFiles/SymbolApiResponseMetadataProviderTest/GetResponseMetadataTests.cs +++ b/src/Mvc/Mvc.Api.Analyzers/test/TestFiles/SymbolApiResponseMetadataProviderTest/GetResponseMetadataTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.AspNetCore.Mvc.Formatters; @@ -75,7 +76,7 @@ public class CustomInvalidProducesResponseTypeAttribute : ProducesResponseTypeAt { private string _statusCode; - public CustomInvalidProducesResponseTypeAttribute() + public CustomInvalidProducesResponseTypeAttribute() : base(0) { } @@ -86,7 +87,7 @@ public CustomInvalidProducesResponseTypeAttribute() set { _statusCode = value; - base.StatusCode = int.Parse(value); + base.StatusCode = int.Parse(value, CultureInfo.InvariantCulture); } } } diff --git a/src/Mvc/Mvc.Core/src/ApiExplorer/ApiConventionMatcher.cs b/src/Mvc/Mvc.Core/src/ApiExplorer/ApiConventionMatcher.cs index e080ce4ef4b6..deb1df2b1646 100644 --- a/src/Mvc/Mvc.Core/src/ApiExplorer/ApiConventionMatcher.cs +++ b/src/Mvc/Mvc.Core/src/ApiExplorer/ApiConventionMatcher.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -145,7 +145,7 @@ bool IsNameMatchSuffix() } index++; - if (name[index] != char.ToUpper(conventionName[0])) + if (name[index] != char.ToUpperInvariant(conventionName[0])) { // Verify the first letter from convention is upper case. In this case 'n' from "name" return false; diff --git a/src/Mvc/Mvc.Core/src/Filters/RequestSizeLimitFilter.cs b/src/Mvc/Mvc.Core/src/Filters/RequestSizeLimitFilter.cs index 7cc2390c23ed..660065e8c97a 100644 --- a/src/Mvc/Mvc.Core/src/Filters/RequestSizeLimitFilter.cs +++ b/src/Mvc/Mvc.Core/src/Filters/RequestSizeLimitFilter.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.Logging; @@ -58,7 +59,7 @@ public void OnAuthorization(AuthorizationFilterContext context) else { maxRequestBodySizeFeature.MaxRequestBodySize = Bytes; - _logger.MaxRequestBodySizeSet(Bytes.ToString()); + _logger.MaxRequestBodySizeSet(Bytes.ToString(CultureInfo.InvariantCulture)); } } } diff --git a/src/Mvc/Mvc.Core/src/Formatters/FormatterMappings.cs b/src/Mvc/Mvc.Core/src/Formatters/FormatterMappings.cs index 81613febfcc8..95b319ddbb6a 100644 --- a/src/Mvc/Mvc.Core/src/Formatters/FormatterMappings.cs +++ b/src/Mvc/Mvc.Core/src/Formatters/FormatterMappings.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.Net.Http.Headers; @@ -103,7 +104,7 @@ private void ValidateContentType(MediaTypeHeaderValue contentType) if (contentType.Type == "*" || contentType.SubType == "*") { throw new ArgumentException( - string.Format(Resources.FormatterMappings_NotValidMediaType, contentType), + string.Format(CultureInfo.CurrentCulture, Resources.FormatterMappings_NotValidMediaType, contentType), nameof(contentType)); } } @@ -119,7 +120,7 @@ private string RemovePeriodIfPresent(string format) { if (format == ".") { - throw new ArgumentException(string.Format(Resources.Format_NotValid, format), nameof(format)); + throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Format_NotValid, format), nameof(format)); } format = format.Substring(1); @@ -128,4 +129,4 @@ private string RemovePeriodIfPresent(string format) return format; } } -} \ No newline at end of file +} diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/DictionaryModelBinder.cs b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/DictionaryModelBinder.cs index 60ca726ed59d..902ca535d58c 100644 --- a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/DictionaryModelBinder.cs +++ b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/DictionaryModelBinder.cs @@ -196,7 +196,7 @@ public override async Task BindModelAsync(ModelBindingContext bindingContext) // again in case this scope is binding a complex type and rewriting // landed on ".key.propertyName" or in case this scope is binding another collection and an // IKeyRewriterValueProvider implementation was first (hiding the original "[key][next key]"). - if (kvp.Value.EndsWith("]")) + if (kvp.Value.EndsWith(']')) { bindingContext.ModelName = ModelNames.CreatePropertyModelName(prefix, kvp.Key); } diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/ServicesModelBinder.cs b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/ServicesModelBinder.cs index 97fcefd1fbe3..34cd732ef333 100644 --- a/src/Mvc/Mvc.Core/src/ModelBinding/Binders/ServicesModelBinder.cs +++ b/src/Mvc/Mvc.Core/src/ModelBinding/Binders/ServicesModelBinder.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { /// /// An which binds models from the request services when a model - /// has the binding source / + /// has the binding source . /// public class ServicesModelBinder : IModelBinder { diff --git a/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs b/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs index e4ee95d0dba1..afa89f9fa89f 100644 --- a/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs +++ b/src/Mvc/Mvc.Core/src/MvcCoreLoggerExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; using System.Security.Claims; @@ -856,7 +857,7 @@ public static void NoActionsMatched(this ILogger logger, IDictionary pair.Key + "=" + Convert.ToString(pair.Value)) + .Select(pair => pair.Key + "=" + Convert.ToString(pair.Value, CultureInfo.InvariantCulture)) .ToArray(); } _noActionsMatched(logger, routeValues, null); @@ -900,7 +901,7 @@ public static void ActionMethodExecuting(this ILogger logger, ControllerContext var convertedArguments = new string[arguments.Length]; for (var i = 0; i < arguments.Length; i++) { - convertedArguments[i] = Convert.ToString(arguments[i]); + convertedArguments[i] = Convert.ToString(arguments[i], CultureInfo.InvariantCulture); } _actionMethodExecutingWithArguments(logger, actionName, convertedArguments, null); @@ -913,7 +914,7 @@ public static void ActionMethodExecuted(this ILogger logger, ControllerContext c if (logger.IsEnabled(LogLevel.Information)) { var actionName = context.ActionDescriptor.DisplayName; - _actionMethodExecuted(logger, actionName, Convert.ToString(result), timeSpan.TotalMilliseconds, null); + _actionMethodExecuted(logger, actionName, Convert.ToString(result, CultureInfo.InvariantCulture), timeSpan.TotalMilliseconds, null); } } @@ -1046,7 +1047,7 @@ public static void NoFormatter( if (context.ContentType.HasValue) { - considered.Add(Convert.ToString(context.ContentType)); + considered.Add(Convert.ToString(context.ContentType, CultureInfo.InvariantCulture)); } _noFormatter(logger, considered, null); @@ -1060,7 +1061,7 @@ public static void FormatterSelected( { if (logger.IsEnabled(LogLevel.Debug)) { - var contentType = Convert.ToString(context.ContentType); + var contentType = Convert.ToString(context.ContentType, CultureInfo.InvariantCulture); _formatterSelected(logger, outputFormatter, contentType, null); } } diff --git a/src/Mvc/Mvc.Core/test/ApplicationModels/AttributeRouteModelTests.cs b/src/Mvc/Mvc.Core/test/ApplicationModels/AttributeRouteModelTests.cs index c6646c110ad4..ac31a503976d 100644 --- a/src/Mvc/Mvc.Core/test/ApplicationModels/AttributeRouteModelTests.cs +++ b/src/Mvc/Mvc.Core/test/ApplicationModels/AttributeRouteModelTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Reflection; using Microsoft.AspNetCore.Routing; using Xunit; @@ -165,6 +166,7 @@ public void ReplaceTokens_InvalidFormat(string template, Dictionary(() => new ConsumesAttribute(contentType)); @@ -69,9 +70,11 @@ public void Constructor_InvalidContentType_Throws(string content, string invalid () => new ConsumesAttribute(contentTypes[0], contentTypes.Skip(1).ToArray())); Assert.Equal( - string.Format("The argument '{0}' is invalid. " + - "Media types which match all types or match all subtypes are not supported.", - invalidContentType), + string.Format( + CultureInfo.CurrentCulture, + "The argument '{0}' is invalid. " + + "Media types which match all types or match all subtypes are not supported.", + invalidContentType), ex.Message); } diff --git a/src/Mvc/Mvc.Core/test/ControllerBaseTest.cs b/src/Mvc/Mvc.Core/test/ControllerBaseTest.cs index a5ec06fb0c24..e29e773bbaba 100644 --- a/src/Mvc/Mvc.Core/test/ControllerBaseTest.cs +++ b/src/Mvc/Mvc.Core/test/ControllerBaseTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Reflection; @@ -1667,7 +1668,7 @@ public void File_WithContents_LastModifiedAndEtag(string lastModifiedString, str // Arrange var controller = new TestableController(); var fileContents = new byte[0]; - var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString); + var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString, CultureInfo.InvariantCulture); var entityTag = (entityTagString == null) ? null : new EntityTagHeaderValue(entityTagString); // Act @@ -1711,7 +1712,7 @@ public void File_WithContentsAndFileDownloadName_LastModifiedAndEtag(string last // Arrange var controller = new TestableController(); var fileContents = new byte[0]; - var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString); + var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString, CultureInfo.InvariantCulture); var entityTag = (entityTagString == null) ? null : new EntityTagHeaderValue(entityTagString); // Act @@ -1755,7 +1756,7 @@ public void File_WithPath_LastModifiedAndEtag(string lastModifiedString, string // Arrange var controller = new TestableController(); var path = Path.GetFullPath("somepath"); - var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString); + var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString, CultureInfo.InvariantCulture); var entityTag = (entityTagString == null) ? null : new EntityTagHeaderValue(entityTagString); // Act @@ -1799,7 +1800,7 @@ public void File_WithPathAndFileDownloadName_LastModifiedAndEtag(string lastModi // Arrange var controller = new TestableController(); var path = Path.GetFullPath("somepath"); - var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString); + var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString, CultureInfo.InvariantCulture); var entityTag = (entityTagString == null) ? null : new EntityTagHeaderValue(entityTagString); // Act @@ -1853,7 +1854,7 @@ public void File_WithStream_LastModifiedAndEtag(string lastModifiedString, strin controller.ControllerContext.HttpContext = mockHttpContext.Object; var fileStream = Stream.Null; - var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString); + var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString, CultureInfo.InvariantCulture); var entityTag = (entityTagString == null) ? null : new EntityTagHeaderValue(entityTagString); // Act @@ -1905,7 +1906,7 @@ public void File_WithStreamAndFileDownloadName_LastModifiedAndEtag(string lastMo controller.ControllerContext.HttpContext = mockHttpContext.Object; var fileStream = Stream.Null; - var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString); + var lastModified = (lastModifiedString == null) ? (DateTimeOffset?)null : DateTimeOffset.Parse(lastModifiedString, CultureInfo.InvariantCulture); var entityTag = (entityTagString == null) ? null : new EntityTagHeaderValue(entityTagString); // Act diff --git a/src/Mvc/Mvc.Core/test/Formatters/JsonOutputFormatterTestBase.cs b/src/Mvc/Mvc.Core/test/Formatters/JsonOutputFormatterTestBase.cs index e10e6ca4f540..2e23227dce52 100644 --- a/src/Mvc/Mvc.Core/test/Formatters/JsonOutputFormatterTestBase.cs +++ b/src/Mvc/Mvc.Core/test/Formatters/JsonOutputFormatterTestBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -86,7 +87,7 @@ public async Task WriteToStreamAsync_UsesCorrectCharacterEncoding( // Arrange var formatter = GetOutputFormatter(); var expectedContent = "\"" + content + "\""; - var mediaType = MediaTypeHeaderValue.Parse(string.Format("application/json; charset={0}", encodingAsString)); + var mediaType = MediaTypeHeaderValue.Parse(string.Format(CultureInfo.InvariantCulture, "application/json; charset={0}", encodingAsString)); var encoding = CreateOrGetSupportedEncoding(formatter, encodingAsString, isDefaultEncoding); diff --git a/src/Mvc/Mvc.Core/test/Formatters/SystemTextJsonInputFormatterTest.cs b/src/Mvc/Mvc.Core/test/Formatters/SystemTextJsonInputFormatterTest.cs index 15dec789822b..78bbd60fca4a 100644 --- a/src/Mvc/Mvc.Core/test/Formatters/SystemTextJsonInputFormatterTest.cs +++ b/src/Mvc/Mvc.Core/test/Formatters/SystemTextJsonInputFormatterTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using System.Text.Json; @@ -157,7 +158,7 @@ private class ShortConverter : JsonConverter { public override short Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return short.Parse(reader.GetString()); + return short.Parse(reader.GetString(), CultureInfo.InvariantCulture); } public override void Write(Utf8JsonWriter writer, short value, JsonSerializerOptions options) @@ -170,7 +171,7 @@ private class DateTimeConverter : JsonConverter { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - return DateTime.Parse(reader.GetString()); + return DateTime.Parse(reader.GetString(), CultureInfo.InvariantCulture); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) diff --git a/src/Mvc/Mvc.Core/test/Infrastructure/ActionSelectorTest.cs b/src/Mvc/Mvc.Core/test/Infrastructure/ActionSelectorTest.cs index 8c508cb3a613..4356fd365bf1 100644 --- a/src/Mvc/Mvc.Core/test/Infrastructure/ActionSelectorTest.cs +++ b/src/Mvc/Mvc.Core/test/Infrastructure/ActionSelectorTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Http; @@ -1122,7 +1123,7 @@ private static ActionDescriptor CreateAction(string area, string controller, str { var actionDescriptor = new ControllerActionDescriptor() { - ActionName = string.Format("Area: {0}, Controller: {1}, Action: {2}", area, controller, action), + ActionName = string.Format(CultureInfo.InvariantCulture, "Area: {0}, Controller: {1}, Action: {2}", area, controller, action), Parameters = new List(), }; diff --git a/src/Mvc/Mvc.Core/test/Infrastructure/AsyncEnumerableReaderTest.cs b/src/Mvc/Mvc.Core/test/Infrastructure/AsyncEnumerableReaderTest.cs index 4a3a861ed4fb..daf1e98d1f5e 100644 --- a/src/Mvc/Mvc.Core/test/Infrastructure/AsyncEnumerableReaderTest.cs +++ b/src/Mvc/Mvc.Core/test/Infrastructure/AsyncEnumerableReaderTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using Xunit; @@ -194,7 +195,7 @@ public static async IAsyncEnumerable TestEnumerable(int count = 3) await Task.Yield(); for (var i = 0; i < count; i++) { - yield return i.ToString(); + yield return i.ToString(CultureInfo.InvariantCulture); } } diff --git a/src/Mvc/Mvc.Core/test/Infrastructure/ObjectResultExecutorTest.cs b/src/Mvc/Mvc.Core/test/Infrastructure/ObjectResultExecutorTest.cs index 395362f8bf46..1fba1ac94a36 100644 --- a/src/Mvc/Mvc.Core/test/Infrastructure/ObjectResultExecutorTest.cs +++ b/src/Mvc/Mvc.Core/test/Infrastructure/ObjectResultExecutorTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -280,8 +281,10 @@ public async Task ExecuteAsync_MatchAllContentType_Throws(string[] contentTypes, var exception = await Assert.ThrowsAsync( () => executor.ExecuteAsync(actionContext, result)); - var expectedMessage = string.Format("The content-type '{0}' added in the 'ContentTypes' property is " + - "invalid. Media types which match all types or match all subtypes are not supported.", + var expectedMessage = string.Format( + CultureInfo.CurrentCulture, + "The content-type '{0}' added in the 'ContentTypes' property is " + + "invalid. Media types which match all types or match all subtypes are not supported.", invalidContentType); Assert.Equal(expectedMessage, exception.Message); } diff --git a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/ComplexTypeModelBinderTest.cs b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/ComplexTypeModelBinderTest.cs index 98bf6a1b6cf5..4a4a795116e3 100644 --- a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/ComplexTypeModelBinderTest.cs +++ b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/ComplexTypeModelBinderTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; +using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.Serialization; @@ -544,6 +545,7 @@ public void CreateModel_ForStructModelType_AsTopLevelObject_ThrowsException() var exception = Assert.Throws(() => binder.CreateModelPublic(bindingContext)); Assert.Equal( string.Format( + CultureInfo.CurrentCulture, "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + "value types and must have a parameterless constructor.", typeof(PointStruct).FullName), @@ -585,6 +587,7 @@ public void CreateModel_ForStructModelType_AsProperty_ThrowsException() var exception = Assert.Throws(() => binder.CreateModelPublic(bindingContext)); Assert.Equal( string.Format( + CultureInfo.CurrentCulture, "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + "value types and must have a parameterless constructor. Alternatively, set the '{1}' property to" + " a non-null value in the '{2}' constructor.", diff --git a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/DateTimeModelBinderTest.cs b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/DateTimeModelBinderTest.cs index 2fd87e551ab1..e44fa480ef28 100644 --- a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/DateTimeModelBinderTest.cs +++ b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/DateTimeModelBinderTest.cs @@ -184,7 +184,7 @@ public async Task UsesSpecifiedStyleToParseModel() { // Arrange var bindingContext = GetBindingContext(); - var expected = DateTime.Parse("2019-06-14T02:30:04.0000000Z"); + var expected = DateTime.Parse("2019-06-14T02:30:04.0000000Z", CultureInfo.InvariantCulture); bindingContext.ValueProvider = new SimpleValueProvider(new CultureInfo("fr-FR")) { { "theModelName", "2019-06-14T02:30:04.0000000Z" } diff --git a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/DictionaryModelBinderTest.cs b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/DictionaryModelBinderTest.cs index 936da88b62c3..60761d62fcc4 100644 --- a/src/Mvc/Mvc.Core/test/ModelBinding/Binders/DictionaryModelBinderTest.cs +++ b/src/Mvc/Mvc.Core/test/ModelBinding/Binders/DictionaryModelBinderTest.cs @@ -220,7 +220,7 @@ public static TheoryData> LongToIntData public async Task BindModel_FallsBackToBindingValues_WithValueTypes(IDictionary dictionary) { // Arrange - var stringDictionary = dictionary.ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value.ToString()); + var stringDictionary = dictionary.ToDictionary(kvp => kvp.Key.ToString(CultureInfo.InvariantCulture), kvp => kvp.Value.ToString(CultureInfo.InvariantCulture)); var binder = new DictionaryModelBinder( new SimpleTypeModelBinder(typeof(long), NullLoggerFactory.Instance), @@ -529,7 +529,7 @@ private static IValueProvider CreateEnumerableValueProvider( { // Convert to an IDictionary then wrap it up. var backingStore = dictionary.ToDictionary( - kvp => string.Format(keyFormat, kvp.Key), + kvp => string.Format(CultureInfo.InvariantCulture, keyFormat, kvp.Key), kvp => (StringValues)kvp.Value); var formCollection = new FormCollection(backingStore); @@ -545,7 +545,7 @@ private static IValueProvider CreateTestValueProvider(string keyFormat, IDiction { // Convert to an IDictionary then wrap it up. var backingStore = dictionary.ToDictionary( - kvp => string.Format(keyFormat, kvp.Key), + kvp => string.Format(CultureInfo.InvariantCulture, keyFormat, kvp.Key), kvp => (object)kvp.Value); return new TestValueProvider(BindingSource.Form, backingStore); diff --git a/src/Mvc/Mvc.Core/test/ModelBinding/ModelBindingHelperTest.cs b/src/Mvc/Mvc.Core/test/ModelBinding/ModelBindingHelperTest.cs index 59ed31da7208..23c3513a1330 100644 --- a/src/Mvc/Mvc.Core/test/ModelBinding/ModelBindingHelperTest.cs +++ b/src/Mvc/Mvc.Core/test/ModelBinding/ModelBindingHelperTest.cs @@ -359,10 +359,12 @@ public void GetPropertyName_ChainedExpression_Throws() var ex = Assert.Throws(() => ModelBindingHelper.GetPropertyName(expression.Body)); - Assert.Equal(string.Format("The passed expression of expression node type '{0}' is invalid." + - " Only simple member access expressions for model properties are supported.", - expression.Body.NodeType), - ex.Message); + Assert.Equal(string.Format( + CultureInfo.CurrentCulture, + "The passed expression of expression node type '{0}' is invalid." + + " Only simple member access expressions for model properties are supported.", + expression.Body.NodeType), + ex.Message); } public static IEnumerable InvalidExpressionDataSet @@ -760,7 +762,7 @@ public void ClearValidationState_ForComplexModel_NonEmptyModelKey(string prefix) // Assert foreach (var entry in dictionary.Keys) { - if (entry.StartsWith(prefix)) + if (entry.StartsWith(prefix, StringComparison.Ordinal)) { Assert.Empty(dictionary[entry].Errors); Assert.Equal(ModelValidationState.Unvalidated, dictionary[entry].ValidationState); diff --git a/src/Mvc/Mvc.Core/test/ModelBinding/TestValueProvider.cs b/src/Mvc/Mvc.Core/test/ModelBinding/TestValueProvider.cs index 98091a6d47cf..f0a5e1f57162 100644 --- a/src/Mvc/Mvc.Core/test/ModelBinding/TestValueProvider.cs +++ b/src/Mvc/Mvc.Core/test/ModelBinding/TestValueProvider.cs @@ -15,13 +15,17 @@ public class TestValueProvider : RouteValueProvider isFromRequest: true); public TestValueProvider(IDictionary values) +#pragma warning disable CA1304 // Specify CultureInfo : base(TestBindingSource, new RouteValueDictionary(values)) +#pragma warning restore CA1304 // Specify CultureInfo { } public TestValueProvider(BindingSource bindingSource, IDictionary values) +#pragma warning disable CA1304 // Specify CultureInfo : base(bindingSource, new RouteValueDictionary(values)) +#pragma warning restore CA1304 // Specify CultureInfo { } } -} \ No newline at end of file +} diff --git a/src/Mvc/Mvc.Core/test/ModelBinding/Validation/DefaultObjectValidatorTests.cs b/src/Mvc/Mvc.Core/test/ModelBinding/Validation/DefaultObjectValidatorTests.cs index 3be2f0e55f89..46b377d5b0c2 100644 --- a/src/Mvc/Mvc.Core/test/ModelBinding/Validation/DefaultObjectValidatorTests.cs +++ b/src/Mvc/Mvc.Core/test/ModelBinding/Validation/DefaultObjectValidatorTests.cs @@ -882,9 +882,9 @@ public static TheoryData ValidCollectionData { new List { - DateTime.Parse("1/1/14"), - DateTime.Parse("2/1/14"), - DateTime.Parse("3/1/14"), + new DateTime(2014, 1, 1), + new DateTime(2014, 2, 1), + new DateTime(2014, 3, 1), }, typeof(ICollection) }, diff --git a/src/Mvc/Mvc.Core/test/ProducesAttributeTests.cs b/src/Mvc/Mvc.Core/test/ProducesAttributeTests.cs index 758b965f044a..5c16de1124a5 100644 --- a/src/Mvc/Mvc.Core/test/ProducesAttributeTests.cs +++ b/src/Mvc/Mvc.Core/test/ProducesAttributeTests.cs @@ -127,9 +127,8 @@ public void ProducesAttribute_InvalidContentType_Throws(string content, string i () => new ProducesAttribute(contentTypes[0], contentTypes.Skip(1).ToArray())); Assert.Equal( - string.Format("The argument '{0}' is invalid. " + - "Media types which match all types or match all subtypes are not supported.", - invalidContentType), + $"The argument '{invalidContentType}' is invalid. " + + "Media types which match all types or match all subtypes are not supported.", ex.Message); } diff --git a/src/Mvc/Mvc.Core/test/Routing/KnownRouteValueConstraintTests.cs b/src/Mvc/Mvc.Core/test/Routing/KnownRouteValueConstraintTests.cs index a28641f8b555..e9a44d919d51 100644 --- a/src/Mvc/Mvc.Core/test/Routing/KnownRouteValueConstraintTests.cs +++ b/src/Mvc/Mvc.Core/test/Routing/KnownRouteValueConstraintTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Abstractions; @@ -295,7 +296,7 @@ private static ActionDescriptor CreateActionDescriptor(string area, string contr { var actionDescriptor = new ControllerActionDescriptor() { - ActionName = string.Format("Area: {0}, Controller: {1}, Action: {2}", area, controller, action), + ActionName = string.Format(CultureInfo.InvariantCulture, "Area: {0}, Controller: {1}, Action: {2}", area, controller, action), }; actionDescriptor.RouteValues.Add("area", area); diff --git a/src/Mvc/Mvc.Cors/test/CorsAuthorizationFilterTest.cs b/src/Mvc/Mvc.Cors/test/CorsAuthorizationFilterTest.cs index 0a3f91ea0003..887b5c0ff151 100644 --- a/src/Mvc/Mvc.Cors/test/CorsAuthorizationFilterTest.cs +++ b/src/Mvc/Mvc.Cors/test/CorsAuthorizationFilterTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Cors.Infrastructure; @@ -199,7 +200,7 @@ private ICorsService GetPassingEngine(bool supportsCredentials = false) { var headers = response1.Headers; headers[CorsConstants.AccessControlMaxAge] = - result1.PreflightMaxAge.Value.TotalSeconds.ToString(); + result1.PreflightMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture); headers[CorsConstants.AccessControlAllowOrigin] = result1.AllowedOrigin; if (result1.SupportsCredentials) { diff --git a/src/Mvc/Mvc.DataAnnotations/test/FileExtensionsAttributeAdapterTest.cs b/src/Mvc/Mvc.DataAnnotations/test/FileExtensionsAttributeAdapterTest.cs index a30cd6cf100e..73c9fb6d9421 100644 --- a/src/Mvc/Mvc.DataAnnotations/test/FileExtensionsAttributeAdapterTest.cs +++ b/src/Mvc/Mvc.DataAnnotations/test/FileExtensionsAttributeAdapterTest.cs @@ -1,8 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Globalization; using Microsoft.AspNetCore.Mvc.DataAnnotations; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Localization; @@ -28,7 +29,7 @@ public void AddValidation_WithoutLocalizationAndDefaultFileExtensions(string ext // FileExtensionsAttribute formats the extension list for the error message var formattedExtensions = string.Join(", ", expectedExtensions.Split(',')); - var expectedErrorMessage = string.Format(attribute.ErrorMessage, nameof(Profile.PhotoFileName), formattedExtensions); + var expectedErrorMessage = string.Format(CultureInfo.CurrentCulture, attribute.ErrorMessage, nameof(Profile.PhotoFileName), formattedExtensions); var adapter = new FileExtensionsAttributeAdapter(attribute, stringLocalizer: null); var context = new ClientModelValidationContext(new ActionContext(), metadata, provider, new Dictionary()); @@ -79,7 +80,7 @@ public void AddValidation_WithoutLocalizationAndCustomFileExtensions(string exte // FileExtensionsAttribute formats the extension list for the error message var formattedExtensions = string.Join(", ", expectedExtensions.Split(',')); - var expectedErrorMessage = string.Format(attribute.ErrorMessage, nameof(Profile.PhotoFileName), formattedExtensions); + var expectedErrorMessage = string.Format(CultureInfo.CurrentCulture, attribute.ErrorMessage, nameof(Profile.PhotoFileName), formattedExtensions); var adapter = new FileExtensionsAttributeAdapter(attribute, stringLocalizer: null); var context = new ClientModelValidationContext(new ActionContext(), metadata, provider, new Dictionary()); diff --git a/src/Mvc/Mvc.Formatters.Xml/test/PersonWrapper.cs b/src/Mvc/Mvc.Formatters.Xml/test/PersonWrapper.cs index adfa86fafcc1..c75241501548 100644 --- a/src/Mvc/Mvc.Formatters.Xml/test/PersonWrapper.cs +++ b/src/Mvc/Mvc.Formatters.Xml/test/PersonWrapper.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; namespace Microsoft.AspNetCore.Mvc.Formatters.Xml { @@ -24,7 +25,7 @@ public PersonWrapper(Person person) public override string ToString() { - return string.Format("{0}, {1}, {2}", Id, Name, Age); + return string.Format(CultureInfo.InvariantCulture, "{0}, {1}, {2}", Id, Name, Age); } public object Unwrap(Type declaredType) @@ -32,4 +33,4 @@ public object Unwrap(Type declaredType) return new Person() { Id = this.Id, Name = this.Name }; } } -} \ No newline at end of file +} diff --git a/src/Mvc/Mvc.Formatters.Xml/test/XmlDataContractSerializerInputFormatterTest.cs b/src/Mvc/Mvc.Formatters.Xml/test/XmlDataContractSerializerInputFormatterTest.cs index 539d75583795..0da7a165bf9b 100644 --- a/src/Mvc/Mvc.Formatters.Xml/test/XmlDataContractSerializerInputFormatterTest.cs +++ b/src/Mvc/Mvc.Formatters.Xml/test/XmlDataContractSerializerInputFormatterTest.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; +using System.Globalization; using System.IO; using System.Linq; using System.Runtime.Serialization; @@ -610,6 +611,7 @@ public async Task ReadAsync_ThrowsWhenNotConfiguredWithRootName() var SubstituteRootNamespace = "http://tempuri.org"; var input = string.Format( + CultureInfo.InvariantCulture, "<{0} xmlns=\"{1}\">1", SubstituteRootName, SubstituteRootNamespace); @@ -630,6 +632,7 @@ public async Task ReadAsync_ReadsWhenConfiguredWithRootName() var SubstituteRootNamespace = "http://tempuri.org"; var input = string.Format( + CultureInfo.InvariantCulture, "<{0} xmlns=\"{1}\">{2}", SubstituteRootName, SubstituteRootNamespace, @@ -666,10 +669,11 @@ public async Task ReadAsync_ThrowsWhenNotConfiguredWithKnownTypes() var InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance"; var input = string.Format( - "1" - + "Some text", - KnownTypeName, - InstanceNamespace); + CultureInfo.InvariantCulture, + "1" + + "Some text", + KnownTypeName, + InstanceNamespace); var formatter = new XmlDataContractSerializerInputFormatter(new MvcOptions()); var contentBytes = Encoding.UTF8.GetBytes(input); var context = GetInputFormatterContext(contentBytes, typeof(DummyClass)); @@ -688,12 +692,13 @@ public async Task ReadAsync_ReadsWhenConfiguredWithKnownTypes() var InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance"; var input = string.Format( - "{2}" - + "{3}", - KnownTypeName, - InstanceNamespace, - expectedInt, - expectedString); + CultureInfo.InvariantCulture, + "{2}" + + "{3}", + KnownTypeName, + InstanceNamespace, + expectedInt, + expectedString); var settings = new DataContractSerializerSettings { KnownTypes = new[] { typeof(SomeDummyClass) } @@ -794,4 +799,4 @@ public override ValueTask DisposeAsync() } } } -} \ No newline at end of file +} diff --git a/src/Mvc/Mvc.Formatters.Xml/test/XmlDataContractSerializerOutputFormatterTest.cs b/src/Mvc/Mvc.Formatters.Xml/test/XmlDataContractSerializerOutputFormatterTest.cs index c0c688374d87..9692f83d5e2e 100644 --- a/src/Mvc/Mvc.Formatters.Xml/test/XmlDataContractSerializerOutputFormatterTest.cs +++ b/src/Mvc/Mvc.Formatters.Xml/test/XmlDataContractSerializerOutputFormatterTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Runtime.Serialization; using System.Text; @@ -505,6 +506,7 @@ public async Task WriteAsync_WritesWhenConfiguredWithRootName() var InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance"; var expectedOutput = string.Format( + CultureInfo.InvariantCulture, "<{0} xmlns:i=\"{2}\" xmlns=\"{1}\">{3}", SubstituteRootName, SubstituteRootNamespace, @@ -548,7 +550,8 @@ public async Task WriteAsync_WritesWhenConfiguredWithKnownTypes() var InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance"; var expectedOutput = string.Format( - "{2}" + CultureInfo.InvariantCulture, + "{2}" + "{3}", KnownTypeName, InstanceNamespace, @@ -594,14 +597,15 @@ public async Task WriteAsync_WritesWhenConfiguredWithPreserveReferences() var SerializationNamespace = "http://schemas.microsoft.com/2003/10/Serialization/"; var expectedOutput = string.Format( - "" + - "" + - "{2}" + - "{3}", - InstanceNamespace, - SerializationNamespace, - sampleId, - sampleName); + CultureInfo.InvariantCulture, + "" + + "" + + "{2}" + + "{3}", + InstanceNamespace, + SerializationNamespace, + sampleId, + sampleName); var child = new Child { Id = sampleId }; var parent = new Parent { Name = sampleName, Children = new List { child } }; @@ -779,4 +783,4 @@ public Customer(int id) public int MyProperty { get; set; } } } -} \ No newline at end of file +} diff --git a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs index 9dcce516650b..461df9bf9fa7 100644 --- a/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs +++ b/src/Mvc/Mvc.NewtonsoftJson/src/NewtonsoftJsonInputFormatter.cs @@ -123,7 +123,8 @@ public override async Task ReadRequestBodyAsync( throw new ArgumentNullException(nameof(encoding)); } - var request = context.HttpContext.Request; + var httpContext = context.HttpContext; + var request = httpContext.Request; var suppressInputFormatterBuffering = _options.SuppressInputFormatterBuffering; @@ -153,7 +154,7 @@ public override async Task ReadRequestBodyAsync( readStream = new FileBufferingReadStream(request.Body, memoryThreshold); // Ensure the file buffer stream is always disposed at the end of a request. - request.HttpContext.Response.RegisterForDispose(readStream); + httpContext.Response.RegisterForDispose(readStream); await readStream.DrainAsync(CancellationToken.None); readStream.Seek(0L, SeekOrigin.Begin); diff --git a/src/Mvc/Mvc.NewtonsoftJson/test/NewtonsoftJsonInputFormatterTest.cs b/src/Mvc/Mvc.NewtonsoftJson/test/NewtonsoftJsonInputFormatterTest.cs index a5eec9f307e6..e9c659531e7c 100644 --- a/src/Mvc/Mvc.NewtonsoftJson/test/NewtonsoftJsonInputFormatterTest.cs +++ b/src/Mvc/Mvc.NewtonsoftJson/test/NewtonsoftJsonInputFormatterTest.cs @@ -4,11 +4,13 @@ using System; using System.Buffers; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.ObjectPool; @@ -399,6 +401,39 @@ public async Task ReadAsync_DoesNotRethrowOverflowExceptions() Assert.Equal("The supplied value is invalid.", modelError.ErrorMessage); } + [Fact] + public async Task ReadAsync_RegistersFileStreamForDisposal() + { + // Arrange + var formatter = new NewtonsoftJsonInputFormatter( + GetLogger(), + _serializerSettings, + ArrayPool.Shared, + _objectPoolProvider, + new MvcOptions(), + new MvcNewtonsoftJsonOptions()); + var httpContext = new Mock(); + IDisposable registerForDispose = null; + + var content = Encoding.UTF8.GetBytes("\"Hello world\""); + httpContext.Setup(h => h.Request.Body).Returns(new NonSeekableReadStream(content, allowSyncReads: false)); + httpContext.Setup(h => h.Request.ContentType).Returns("application/json"); + httpContext.Setup(h => h.Response.RegisterForDispose(It.IsAny())) + .Callback((IDisposable disposable) => registerForDispose = disposable) + .Verifiable(); + + var formatterContext = CreateInputFormatterContext(typeof(string), httpContext.Object); + + // Act + var result = await formatter.ReadAsync(formatterContext); + + // Assert + Assert.Equal("Hello world", result.Model); + Assert.NotNull(registerForDispose); + Assert.IsType(registerForDispose); + httpContext.Verify(); + } + private class TestableJsonInputFormatter : NewtonsoftJsonInputFormatter { public TestableJsonInputFormatter(JsonSerializerSettings settings, ObjectPoolProvider objectPoolProvider) @@ -494,7 +529,7 @@ private class IncorrectShortConverter : JsonConverter { public override short ReadJson(JsonReader reader, Type objectType, short existingValue, bool hasExistingValue, JsonSerializer serializer) { - return short.Parse(reader.Value.ToString()); + return short.Parse(reader.Value.ToString(), CultureInfo.InvariantCulture); } public override void WriteJson(JsonWriter writer, short value, JsonSerializer serializer) diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/CSharpCompiler.cs b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/CSharpCompiler.cs index d9b20c8c7e22..0d31068add54 100644 --- a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/CSharpCompiler.cs +++ b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/CSharpCompiler.cs @@ -125,7 +125,7 @@ private EmitOptions GetEmitOptions(DependencyContextCompilationOptions dependenc else { // Based on https://github.com/dotnet/roslyn/blob/1d28ff9ba248b332de3c84d23194a1d7bde07e4d/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs#L624-L640 - switch (dependencyContextOptions.DebugType.ToLower()) + switch (dependencyContextOptions.DebugType.ToLowerInvariant()) { case "none": // There isn't a way to represent none in DebugInformationFormat. diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/ChecksumValidator.cs b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/ChecksumValidator.cs index d58319a30806..33f6d74bf6d6 100644 --- a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/ChecksumValidator.cs +++ b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/ChecksumValidator.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Razor.Hosting; using Microsoft.AspNetCore.Razor.Language; @@ -109,7 +110,7 @@ private static bool ChecksumsEqual(string checksum, byte[] bytes) for (var i = 0; i < bytes.Length; i++) { - var text = bytes[i].ToString("x2"); + var text = bytes[i].ToString("x2", CultureInfo.InvariantCulture); if (checksum[i * 2] != text[0] || checksum[i * 2 + 1] != text[1]) { return false; diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/CompilationFailedExceptionFactory.cs b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/CompilationFailedExceptionFactory.cs index 86cfc0a2239d..359e8977dec3 100644 --- a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/CompilationFailedExceptionFactory.cs +++ b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/CompilationFailedExceptionFactory.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Razor.Language; @@ -133,7 +134,7 @@ private static DiagnosticMessage CreateDiagnosticMessage( string filePath) { var sourceSpan = razorDiagnostic.Span; - var message = razorDiagnostic.GetMessage(); + var message = razorDiagnostic.GetMessage(CultureInfo.CurrentCulture); return new DiagnosticMessage( message: message, formattedMessage: razorDiagnostic.ToString(), diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RazorRuntimeCompilationLoggerExtensions.cs b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RazorRuntimeCompilationLoggerExtensions.cs index 51ae2dc03df6..dd644942409f 100644 --- a/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RazorRuntimeCompilationLoggerExtensions.cs +++ b/src/Mvc/Mvc.Razor.RuntimeCompilation/src/RazorRuntimeCompilationLoggerExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using Microsoft.AspNetCore.Razor.Language; using Microsoft.Extensions.Logging; @@ -169,7 +170,7 @@ public static void MalformedPageDirective(this ILogger logger, string filePath, var messages = new string[diagnostics.Count]; for (var i = 0; i < diagnostics.Count; i++) { - messages[i] = diagnostics[i].GetMessage(); + messages[i] = diagnostics[i].GetMessage(CultureInfo.CurrentCulture); } _malformedPageDirective(logger, filePath, messages, null); diff --git a/src/Mvc/Mvc.Razor.RuntimeCompilation/test/CompilerFailedExceptionFactoryTest.cs b/src/Mvc/Mvc.Razor.RuntimeCompilation/test/CompilerFailedExceptionFactoryTest.cs index c32de460c155..31ca08c2ebae 100644 --- a/src/Mvc/Mvc.Razor.RuntimeCompilation/test/CompilerFailedExceptionFactoryTest.cs +++ b/src/Mvc/Mvc.Razor.RuntimeCompilation/test/CompilerFailedExceptionFactoryTest.cs @@ -1,6 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -183,7 +184,7 @@ public void GetCompilationFailedResult_GroupsMessages() Assert.Collection(failure.Messages, message => { - Assert.Equal(diagnostics[0].GetMessage(), message.Message); + Assert.Equal(diagnostics[0].GetMessage(CultureInfo.CurrentCulture), message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(3, message.StartLine); Assert.Equal(17, message.StartColumn); @@ -192,7 +193,7 @@ public void GetCompilationFailedResult_GroupsMessages() }, message => { - Assert.Equal(diagnostics[1].GetMessage(), message.Message); + Assert.Equal(diagnostics[1].GetMessage(CultureInfo.CurrentCulture), message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(5, message.StartLine); Assert.Equal(6, message.StartColumn); @@ -201,7 +202,7 @@ public void GetCompilationFailedResult_GroupsMessages() }, message => { - Assert.Equal(diagnostics[2].GetMessage(), message.Message); + Assert.Equal(diagnostics[2].GetMessage(CultureInfo.CurrentCulture), message.Message); Assert.Equal(viewPath, message.SourceFilePath); Assert.Equal(0, message.StartLine); Assert.Equal(-1, message.StartColumn); @@ -216,7 +217,7 @@ public void GetCompilationFailedResult_GroupsMessages() Assert.Collection(failure.Messages, message => { - Assert.Equal(diagnostics[3].GetMessage(), message.Message); + Assert.Equal(diagnostics[3].GetMessage(CultureInfo.CurrentCulture), message.Message); Assert.Equal(viewImportsPath, message.SourceFilePath); Assert.Equal(4, message.StartLine); Assert.Equal(8, message.StartColumn); diff --git a/src/Mvc/Mvc.RazorPages/src/ApplicationModels/DefaultPageApplicationModelPartsProvider.cs b/src/Mvc/Mvc.RazorPages/src/ApplicationModels/DefaultPageApplicationModelPartsProvider.cs index d120da58d2e0..be5c7b7b7e38 100644 --- a/src/Mvc/Mvc.RazorPages/src/ApplicationModels/DefaultPageApplicationModelPartsProvider.cs +++ b/src/Mvc/Mvc.RazorPages/src/ApplicationModels/DefaultPageApplicationModelPartsProvider.cs @@ -224,7 +224,7 @@ internal static bool TryParseHandlerMethod(string methodName, out string httpMet handler = null; // Handler method names always start with "On" - if (!methodName.StartsWith("On") || methodName.Length <= "On".Length) + if (!methodName.StartsWith("On", StringComparison.Ordinal) || methodName.Length <= "On".Length) { return false; } diff --git a/src/Mvc/Mvc.RazorPages/src/PageLoggerExtensions.cs b/src/Mvc/Mvc.RazorPages/src/PageLoggerExtensions.cs index 39d07f8145ef..d07e1ea65a8b 100644 --- a/src/Mvc/Mvc.RazorPages/src/PageLoggerExtensions.cs +++ b/src/Mvc/Mvc.RazorPages/src/PageLoggerExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; @@ -161,7 +162,7 @@ public static void ExecutingHandlerMethod(this ILogger logger, PageContext conte var convertedArguments = new string[arguments.Length]; for (var i = 0; i < arguments.Length; i++) { - convertedArguments[i] = Convert.ToString(arguments[i]); + convertedArguments[i] = Convert.ToString(arguments[i], CultureInfo.InvariantCulture); } _handlerMethodExecutingWithArguments(logger, handlerName, convertedArguments, null); @@ -184,7 +185,7 @@ public static void ExecutedHandlerMethod(this ILogger logger, PageContext contex if (logger.IsEnabled(LogLevel.Information)) { var handlerName = handler.MethodInfo.Name; - _handlerMethodExecuted(logger, handlerName, Convert.ToString(result), null); + _handlerMethodExecuted(logger, handlerName, Convert.ToString(result, CultureInfo.InvariantCulture), null); } } @@ -192,7 +193,7 @@ public static void ExecutedImplicitHandlerMethod(this ILogger logger, IActionRes { if (logger.IsEnabled(LogLevel.Information)) { - _implicitHandlerMethodExecuted(logger, Convert.ToString(result), null); + _implicitHandlerMethodExecuted(logger, Convert.ToString(result, CultureInfo.InvariantCulture), null); } } diff --git a/src/Mvc/Mvc.TagHelpers/src/PartialTagHelper.cs b/src/Mvc/Mvc.TagHelpers/src/PartialTagHelper.cs index 01ab2aabc36b..4115c4e0f96a 100644 --- a/src/Mvc/Mvc.TagHelpers/src/PartialTagHelper.cs +++ b/src/Mvc/Mvc.TagHelpers/src/PartialTagHelper.cs @@ -113,7 +113,7 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu if (output == null) { - throw new ArgumentNullException(nameof(context)); + throw new ArgumentNullException(nameof(output)); } // Reset the TagName. We don't want `partial` to render. diff --git a/src/Mvc/Mvc.ViewFeatures/src/DefaultHtmlGenerator.cs b/src/Mvc/Mvc.ViewFeatures/src/DefaultHtmlGenerator.cs index 4169b94cba2d..76491f0373b3 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/DefaultHtmlGenerator.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/DefaultHtmlGenerator.cs @@ -1433,7 +1433,7 @@ protected virtual void AddMaxLengthAttribute( if (maxLengthValue.HasValue) { - tagBuilder.MergeAttribute("maxlength", maxLengthValue.Value.ToString()); + tagBuilder.MergeAttribute("maxlength", maxLengthValue.Value.ToString(CultureInfo.InvariantCulture)); } } diff --git a/src/Mvc/Mvc.ViewFeatures/src/MvcViewFeaturesLoggerExtensions.cs b/src/Mvc/Mvc.ViewFeatures/src/MvcViewFeaturesLoggerExtensions.cs index 635c3e315d31..19671f344fd4 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/MvcViewFeaturesLoggerExtensions.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/MvcViewFeaturesLoggerExtensions.cs @@ -1,10 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using Microsoft.AspNetCore.Mvc.ViewComponents; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.Extensions.Logging; @@ -148,7 +149,7 @@ private static string[] GetFormattedArguments(object[] arguments) var formattedArguments = new string[arguments.Length]; for (var i = 0; i < formattedArguments.Length; i++) { - formattedArguments[i] = Convert.ToString(arguments[i]); + formattedArguments[i] = Convert.ToString(arguments[i], CultureInfo.InvariantCulture); } return formattedArguments; @@ -165,7 +166,7 @@ public static void ViewComponentExecuted( logger, context.ViewComponentDescriptor.DisplayName, timespan.TotalMilliseconds, - Convert.ToString(result), + Convert.ToString(result, CultureInfo.InvariantCulture), null); } diff --git a/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/StaticComponentRenderer.cs b/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/StaticComponentRenderer.cs index 7a8a8dd62ded..9741f39b3216 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/StaticComponentRenderer.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/RazorComponents/StaticComponentRenderer.cs @@ -99,7 +99,7 @@ private string GetContextBaseUri(HttpRequest request) // PathBase may be "/" or "/some/thing", but to be a well-formed base URI // it has to end with a trailing slash - return result.EndsWith("/") ? result : result += "/"; + return result.EndsWith('/') ? result : result += "/"; } } } diff --git a/src/Mvc/Mvc.ViewFeatures/test/Buffers/ViewBufferTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Buffers/ViewBufferTest.cs index baee0d7003ee..542be7965d9e 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/Buffers/ViewBufferTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/Buffers/ViewBufferTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -70,7 +71,7 @@ public void Append_CreatesOnePage() { // Arrange var buffer = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 32); - var expected = Enumerable.Range(0, 32).Select(i => i.ToString()); + var expected = Enumerable.Range(0, 32).Select(i => i.ToString(CultureInfo.InvariantCulture)); // Act foreach (var item in expected) @@ -88,7 +89,7 @@ public void Append_CreatesTwoPages() { // Arrange var buffer = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 32); - var expected = Enumerable.Range(0, 32).Select(i => i.ToString()); + var expected = Enumerable.Range(0, 32).Select(i => i.ToString(CultureInfo.InvariantCulture)); // Act foreach (var item in expected) @@ -115,8 +116,8 @@ public void Append_CreatesManyPages() { // Arrange var buffer = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 32); - var expected0 = Enumerable.Range(0, 32).Select(i => i.ToString()); - var expected1 = Enumerable.Range(32, 32).Select(i => i.ToString()); + var expected0 = Enumerable.Range(0, 32).Select(i => i.ToString(CultureInfo.InvariantCulture)); + var expected1 = Enumerable.Range(32, 32).Select(i => i.ToString(CultureInfo.InvariantCulture)); // Act foreach (var item in expected0) @@ -471,7 +472,7 @@ public void MoveTo_ViewBuffer_MultiplePages() { original.AppendHtml($"original-{i}"); } - + for (var i = 0; i < 9; i++) { other.AppendHtml($"other-{i}"); diff --git a/src/Mvc/Mvc.ViewFeatures/test/DefaultHtmlGeneratorTest.cs b/src/Mvc/Mvc.ViewFeatures/test/DefaultHtmlGeneratorTest.cs index e9c08910c64e..4c657379ed89 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/DefaultHtmlGeneratorTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/DefaultHtmlGeneratorTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Globalization; using System.IO; using System.Linq; using System.Text.Encodings.Web; @@ -212,7 +213,7 @@ public void GenerateTextArea_RendersMaxLength(string expression, int expectedVal // Assert var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength"); - Assert.Equal(expectedValue, int.Parse(attribute.Value)); + Assert.Equal(expectedValue, int.Parse(attribute.Value, CultureInfo.InvariantCulture)); } [Theory] @@ -236,7 +237,7 @@ public void GeneratePassword_RendersMaxLength(string expression, int expectedVal // Assert var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength"); - Assert.Equal(expectedValue, int.Parse(attribute.Value)); + Assert.Equal(expectedValue, int.Parse(attribute.Value, CultureInfo.InvariantCulture)); } [Theory] @@ -260,7 +261,7 @@ public void GenerateTextBox_RendersMaxLength(string expression, int expectedValu // Assert var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength"); - Assert.Equal(expectedValue, int.Parse(attribute.Value)); + Assert.Equal(expectedValue, int.Parse(attribute.Value, CultureInfo.InvariantCulture)); } [Fact] @@ -282,7 +283,7 @@ public void GenerateTextBox_RendersMaxLength_WithMinimumValueFromBothAttributes( // Assert var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength"); - Assert.Equal(Math.Min(ModelWithMaxLengthMetadata.MaxLengthAttributeValue, ModelWithMaxLengthMetadata.StringLengthAttributeValue), int.Parse(attribute.Value)); + Assert.Equal(Math.Min(ModelWithMaxLengthMetadata.MaxLengthAttributeValue, ModelWithMaxLengthMetadata.StringLengthAttributeValue), int.Parse(attribute.Value, CultureInfo.InvariantCulture)); } [Fact] @@ -328,7 +329,7 @@ public void GenerateTextBox_SearchType_RendersMaxLength(string expression, int e // Assert var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength"); - Assert.Equal(expectedValue, int.Parse(attribute.Value)); + Assert.Equal(expectedValue, int.Parse(attribute.Value, CultureInfo.InvariantCulture)); } [Theory] diff --git a/src/Mvc/Mvc.ViewFeatures/test/Infrastructure/TempDataSerializerTestBase.cs b/src/Mvc/Mvc.ViewFeatures/test/Infrastructure/TempDataSerializerTestBase.cs index 93fb4df0e266..30bb0fd6ff0f 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/Infrastructure/TempDataSerializerTestBase.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/Infrastructure/TempDataSerializerTestBase.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using Xunit; namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure @@ -183,7 +184,7 @@ public virtual void RoundTripTest_DateTimeToString() var value = new DateTime(2009, 1, 1, 12, 37, 43); var input = new Dictionary { - { key, value.ToString() } + { key, value.ToString(CultureInfo.InvariantCulture) } }; // Act @@ -192,7 +193,7 @@ public virtual void RoundTripTest_DateTimeToString() // Assert var roundTripValue = Assert.IsType(values[key]); - Assert.Equal(value.ToString(), roundTripValue); + Assert.Equal(value.ToString(CultureInfo.InvariantCulture), roundTripValue); } [Fact] diff --git a/src/Mvc/Mvc.ViewFeatures/test/RazorComponents/HtmlRendererTest.cs b/src/Mvc/Mvc.ViewFeatures/test/RazorComponents/HtmlRendererTest.cs index 67778e416355..871c7d01e412 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/RazorComponents/HtmlRendererTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/RazorComponents/HtmlRendererTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Runtime.ExceptionServices; using System.Text.Encodings.Web; using System.Threading.Tasks; @@ -620,7 +621,7 @@ protected override async Task OnInitializedAsync() protected override void BuildRenderTree(RenderTreeBuilder builder) { builder.OpenElement(0, "p"); - builder.AddContent(1, Value.ToString()); + builder.AddContent(1, Value.ToString(CultureInfo.InvariantCulture)); builder.CloseElement(); if (!Nested) { @@ -650,7 +651,7 @@ protected override async Task OnInitializedAsync() protected override void BuildRenderTree(RenderTreeBuilder builder) { builder.OpenElement(0, "p"); - builder.AddContent(1, Value.ToString()); + builder.AddContent(1, Value.ToString(CultureInfo.InvariantCulture)); builder.CloseElement(); } } diff --git a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperCheckboxTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperCheckboxTest.cs index ab357622556a..4c8f91b42974 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperCheckboxTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperCheckboxTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Globalization; using System.IO; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ViewFeatures; @@ -592,7 +593,7 @@ public void CheckBoxForWithNonNullContainer_UsesPropertyValue(bool value, string $@"" + @""; - expected = string.Format(expected, expectedChecked); + expected = string.Format(CultureInfo.InvariantCulture, expected, expectedChecked); var viewData = GetTestModelViewData(); viewData.Model = new TestModel @@ -662,7 +663,7 @@ public void CheckBoxFor_UsesModelStateAttemptedValue(string attemptedValue, stri $@"" + @""; - expected = string.Format(expected, expectedChecked); + expected = string.Format(CultureInfo.InvariantCulture, expected, expectedChecked); var viewData = GetTestModelViewData(); var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData); diff --git a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperFormTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperFormTest.cs index ceebb8f7126c..0b6814cec9be 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperFormTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperFormTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text.Encodings.Web; @@ -124,7 +125,7 @@ public void BeginForm_RendersExpectedValues_WithDefaultArguments() var path = "/Path"; var queryString = "?query=string"; var expectedAction = pathBase + path + queryString; - var expectedStartTag = string.Format("
", expectedAction); + var expectedStartTag = string.Format(CultureInfo.InvariantCulture, "", expectedAction); // IUrlHelper should not be used in this scenario. var urlHelper = new Mock(MockBehavior.Strict); @@ -172,7 +173,7 @@ public void BeginForm_RendersExpectedValues_WithDefaultArgumentsAndHtmlAttribute var queryString = "?query=string"; var expectedAction = pathBase + path + queryString; var htmlAttributes = new { p1_name = "p1-value" }; - var expectedStartTag = string.Format("", + var expectedStartTag = string.Format(CultureInfo.InvariantCulture, "", expectedAction, GetHtmlAttributesAsString(htmlAttributes)); @@ -225,6 +226,7 @@ public void BeginForm_RendersExpectedValues( // Arrange var expectedAction = "http://localhost/Hello/World"; var expectedStartTag = string.Format( + CultureInfo.InvariantCulture, "", expectedAction, method.ToString().ToLowerInvariant(), @@ -273,6 +275,7 @@ public void BeginRouteForm_RendersExpectedValues( // Arrange var expectedAction = "http://localhost/Hello/World"; var expectedStartTag = string.Format( + CultureInfo.InvariantCulture, "", expectedAction, method.ToString().ToLowerInvariant(), @@ -812,7 +815,7 @@ private string GetHtmlAttributesAsString(object htmlAttributes) var dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); return string.Join( string.Empty, - dictionary.Select(keyValue => string.Format(" {0}=\"HtmlEncode[[{1}]]\"", keyValue.Key, keyValue.Value))); + dictionary.Select(keyValue => string.Format(CultureInfo.InvariantCulture, " {0}=\"HtmlEncode[[{1}]]\"", keyValue.Key, keyValue.Value))); } } } diff --git a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperLinkGenerationTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperLinkGenerationTest.cs index be91f776922b..915d143754e9 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperLinkGenerationTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperLinkGenerationTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.Internal; @@ -38,29 +39,33 @@ public static IEnumerable ActionLinkGenerationData [Theory] [MemberData(nameof(ActionLinkGenerationData))] public void ActionLink_GeneratesLink_WithExpectedValues( - string action, - string controller, - object routeValues, - string protocol, - string hostname, - string fragment, - object htmlAttributes) + string action, + string controller, + object routeValues, + string protocol, + string hostname, + string fragment, + object htmlAttributes) { //Arrange - string expectedLink = string.Format(@"HtmlEncode[[Details]]", - protocol, - hostname, - controller, - action, - GetRouteValuesAsString(routeValues), - fragment, - GetHtmlAttributesAsString(htmlAttributes)); + var expectedLink = string.Format( + CultureInfo.InvariantCulture, + @"HtmlEncode[[Details]]", + protocol, + hostname, + controller, + action, + GetRouteValuesAsString(routeValues), + fragment, + GetHtmlAttributesAsString(htmlAttributes)); expectedLink = expectedLink.Replace("HtmlEncode[[]]", string.Empty); var urlHelper = new Mock(); urlHelper.Setup(h => h.Action(It.IsAny())) .Returns((actionContext) => - string.Format("{0}{1}{2}{3}{4}{5}", + string.Format( + CultureInfo.InvariantCulture, + "{0}{1}{2}{3}{4}{5}", actionContext.Protocol, actionContext.Host, actionContext.Controller, @@ -72,14 +77,14 @@ public void ActionLink_GeneratesLink_WithExpectedValues( // Act var actualLink = htmlHelper.ActionLink( - linkText: "Details", - actionName: action, - controllerName: controller, - protocol: protocol, - hostname: hostname, - fragment: fragment, - routeValues: routeValues, - htmlAttributes: htmlAttributes); + linkText: "Details", + actionName: action, + controllerName: controller, + protocol: protocol, + hostname: hostname, + fragment: fragment, + routeValues: routeValues, + htmlAttributes: htmlAttributes); // Assert Assert.Equal(expectedLink, HtmlContentUtilities.HtmlContentToString(actualLink)); @@ -106,27 +111,31 @@ public static IEnumerable RouteLinkGenerationData [Theory] [MemberData(nameof(RouteLinkGenerationData))] public void RouteLink_GeneratesLink_WithExpectedValues( - string routeName, - object routeValues, - string protocol, - string hostname, - string fragment, - object htmlAttributes) + string routeName, + object routeValues, + string protocol, + string hostname, + string fragment, + object htmlAttributes) { //Arrange - string expectedLink = string.Format(@"HtmlEncode[[Details]]", - protocol, - hostname, - GetRouteValuesAsString(routeValues), - fragment, - GetHtmlAttributesAsString(htmlAttributes)); + var expectedLink = string.Format( + CultureInfo.InvariantCulture, + @"HtmlEncode[[Details]]", + protocol, + hostname, + GetRouteValuesAsString(routeValues), + fragment, + GetHtmlAttributesAsString(htmlAttributes)); expectedLink = expectedLink.Replace("HtmlEncode[[]]", string.Empty); var urlHelper = new Mock(); urlHelper .Setup( h => h.RouteUrl(It.IsAny())).Returns((context) => - string.Format("{0}{1}{2}{3}", + string.Format( + CultureInfo.InvariantCulture, + "{0}{1}{2}{3}", context.Protocol, context.Host, GetRouteValuesAsString(context.Values), @@ -136,13 +145,13 @@ public void RouteLink_GeneratesLink_WithExpectedValues( // Act var actualLink = htmlHelper.RouteLink( - linkText: "Details", - routeName: routeName, - protocol: protocol, - hostName: hostname, - fragment: fragment, - routeValues: routeValues, - htmlAttributes: htmlAttributes); + linkText: "Details", + routeName: routeName, + protocol: protocol, + hostName: hostname, + fragment: fragment, + routeValues: routeValues, + htmlAttributes: htmlAttributes); // Assert Assert.Equal(expectedLink, HtmlContentUtilities.HtmlContentToString(actualLink)); @@ -151,13 +160,13 @@ public void RouteLink_GeneratesLink_WithExpectedValues( private string GetRouteValuesAsString(object routeValues) { var dict = PropertyHelper.ObjectToDictionary(routeValues); - return string.Join(string.Empty, dict.Select(kvp => string.Format("{0}={1}", kvp.Key, kvp.Value.ToString()))); + return string.Join(string.Empty, dict.Select(kvp => string.Format(CultureInfo.InvariantCulture, "{0}={1}", kvp.Key, kvp.Value.ToString()))); } private string GetHtmlAttributesAsString(object routeValues) { var dict = PropertyHelper.ObjectToDictionary(routeValues); - return string.Join(string.Empty, dict.Select(kvp => string.Format(" {0}=\"HtmlEncode[[{1}]]\"", kvp.Key, kvp.Value.ToString()))); + return string.Join(string.Empty, dict.Select(kvp => string.Format(CultureInfo.InvariantCulture, " {0}=\"HtmlEncode[[{1}]]\"", kvp.Key, kvp.Value.ToString()))); } } } diff --git a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperValueExtensionsTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperValueExtensionsTest.cs index f1776922a976..e474c26972db 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperValueExtensionsTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperValueExtensionsTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Xunit; namespace Microsoft.AspNetCore.Mvc.Rendering @@ -70,6 +71,7 @@ private class SomeModel public override string ToString() { return string.Format( + CultureInfo.InvariantCulture, "{{ SomeProperty = {0} }}", SomeProperty ?? "(null)"); } } diff --git a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperValueTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperValueTest.cs index 629a3808658b..fd09a3902955 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperValueTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/Rendering/HtmlHelperValueTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Testing; @@ -241,6 +242,7 @@ private sealed class TestModel public override string ToString() { return string.Format( + CultureInfo.InvariantCulture, "{{ StringProperty = {0}, ObjectProperty = {1} }}", StringProperty ?? "(null)", ObjectProperty ?? "(null)"); diff --git a/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/HelperPerformanceBenchmark.cs b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/HelperPerformanceBenchmark.cs index 572a11a73bb2..81763d7549ff 100644 --- a/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/HelperPerformanceBenchmark.cs +++ b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/HelperPerformanceBenchmark.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Linq; using System.Reflection; @@ -44,6 +45,6 @@ public HelperPerformanceBenchmark() : base( { } - protected override object Model => _rand.Next().ToString(); + protected override object Model => _rand.Next().ToString(CultureInfo.InvariantCulture); } } diff --git a/src/Mvc/samples/MvcSandbox/SlugifyParameterTransformer.cs b/src/Mvc/samples/MvcSandbox/SlugifyParameterTransformer.cs index 7c5b8c396fed..845a20bed27b 100644 --- a/src/Mvc/samples/MvcSandbox/SlugifyParameterTransformer.cs +++ b/src/Mvc/samples/MvcSandbox/SlugifyParameterTransformer.cs @@ -12,7 +12,7 @@ public class SlugifyParameterTransformer : IOutboundParameterTransformer public string TransformOutbound(object value) { // Slugify value - return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2", RegexOptions.None, TimeSpan.FromMilliseconds(100)).ToLower(); + return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2", RegexOptions.None, TimeSpan.FromMilliseconds(100)).ToLowerInvariant(); } } } diff --git a/src/Mvc/shared/Mvc.Views.TestCommon/TestRazorCompiledItem.cs b/src/Mvc/shared/Mvc.Views.TestCommon/TestRazorCompiledItem.cs index aed8172d3ec1..e3b94b6c49e7 100644 --- a/src/Mvc/shared/Mvc.Views.TestCommon/TestRazorCompiledItem.cs +++ b/src/Mvc/shared/Mvc.Views.TestCommon/TestRazorCompiledItem.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Security.Cryptography; using System.Text; @@ -58,7 +59,7 @@ public static string GetChecksum(string content) for (var i = 0; i < bytes.Length; i++) { // The x2 format means lowercase hex, where each byte is a 2-character string. - result.Append(bytes[i].ToString("x2")); + result.Append(bytes[i].ToString("x2", CultureInfo.InvariantCulture)); } return result.ToString(); diff --git a/src/Mvc/test/Mvc.FunctionalTests/BasicTests.cs b/src/Mvc/test/Mvc.FunctionalTests/BasicTests.cs index d935f9a2a5ac..706c85eea0c4 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/BasicTests.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/BasicTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -268,6 +269,7 @@ public async Task JsonHelperWithSettings_RendersJson_WithNamesUnchanged() // Arrange var json = "{\"id\":9000,\"FullName\":\"John \\u003cb\\u003eSmith\\u003c/b\\u003e\"}"; var expectedBody = string.Format( + CultureInfo.InvariantCulture, @"", @@ -290,6 +292,7 @@ public async Task JsonHelperWithSettings_RendersJson_WithSnakeCaseNames() // Arrange var json = "{\"id\":9000,\"full_name\":\"John \\u003cb\\u003eSmith\\u003c/b\\u003e\"}"; var expectedBody = string.Format( + CultureInfo.InvariantCulture, @"", diff --git a/src/Mvc/test/Mvc.FunctionalTests/HtmlGenerationTest.cs b/src/Mvc/test/Mvc.FunctionalTests/HtmlGenerationTest.cs index dfaaa2fb5fd3..d03a6eadb37b 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/HtmlGenerationTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/HtmlGenerationTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -12,6 +13,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.Testing; using Xunit; namespace Microsoft.AspNetCore.Mvc.FunctionalTests @@ -61,8 +63,6 @@ public static TheoryData WebPagesData { "EmployeeList", "/HtmlGeneration_Home/EmployeeList" }, // Testing the EnvironmentTagHelper { "Environment", null }, - // Testing the ImageTagHelper - { "Image", null }, // Testing InputTagHelper with File { "Input", null }, // Testing the LinkTagHelper @@ -132,12 +132,19 @@ public async Task HtmlGenerationWebSite_GeneratesExpectedResults(string action, responseContent = responseContent.Replace(forgeryToken, "{0}"); ResourceFile.UpdateFile(_resourcesAssembly, outputFile, expectedContent, responseContent); #else - expectedContent = string.Format(expectedContent, forgeryToken); + expectedContent = string.Format(CultureInfo.InvariantCulture, expectedContent, forgeryToken); Assert.Equal(expectedContent.Trim(), responseContent, ignoreLineEndingDifferences: true); #endif } } + [Fact] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/25206")] + public async Task HtmlGenerationWebSite_GeneratesExpectedResults_WithImageData() + { + await HtmlGenerationWebSite_GeneratesExpectedResults("Image", antiforgeryPath: null); + } + [Fact] public async Task HtmlGenerationWebSite_LinkGeneration_With21CompatibilityBehavior() { @@ -224,7 +231,7 @@ public async Task HtmlGenerationWebSite_GenerateEncodedResults(string action, st responseContent = responseContent.Replace(forgeryToken, "{0}"); ResourceFile.UpdateFile(_resourcesAssembly, outputFile, expectedContent, responseContent); #else - expectedContent = string.Format(expectedContent, forgeryToken); + expectedContent = string.Format(CultureInfo.InvariantCulture, expectedContent, forgeryToken); Assert.Equal(expectedContent.Trim(), responseContent, ignoreLineEndingDifferences: true); #endif } @@ -294,7 +301,7 @@ public async Task ValidationTagHelpers_GeneratesExpectedSpansAndDivs() responseContent = responseContent.Replace(forgeryToken, "{0}"); ResourceFile.UpdateFile(_resourcesAssembly, outputFile, expectedContent, responseContent); #else - expectedContent = string.Format(expectedContent, forgeryToken); + expectedContent = string.Format(CultureInfo.InvariantCulture, expectedContent, forgeryToken); Assert.Equal(expectedContent.Trim(), responseContent, ignoreLineEndingDifferences: true); #endif } diff --git a/src/Mvc/test/Mvc.FunctionalTests/InputFormatterTests.cs b/src/Mvc/test/Mvc.FunctionalTests/InputFormatterTests.cs index 0283623d1af3..52267ade6f74 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/InputFormatterTests.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/InputFormatterTests.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using System.Net; using System.Net.Http; using System.Net.Http.Json; @@ -31,7 +32,7 @@ public async Task CheckIfXmlInputFormatterIsBeingCalled() var sampleInputInt = 10; var input = "" + "" - + sampleInputInt.ToString() + ""; + + sampleInputInt + "
"; var content = new StringContent(input, Encoding.UTF8, "application/xml"); // Act @@ -39,7 +40,7 @@ public async Task CheckIfXmlInputFormatterIsBeingCalled() // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(sampleInputInt.ToString(), await response.Content.ReadAsStringAsync()); + Assert.Equal(sampleInputInt.ToString(CultureInfo.InvariantCulture), await response.Content.ReadAsStringAsync()); } [Theory] diff --git a/src/Mvc/test/Mvc.FunctionalTests/JsonInputFormatterTestBase.cs b/src/Mvc/test/Mvc.FunctionalTests/JsonInputFormatterTestBase.cs index 966d0a51e964..f29be8bddd46 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/JsonInputFormatterTestBase.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/JsonInputFormatterTestBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -43,7 +44,7 @@ public async Task JsonInputFormatter_IsSelectedForJsonRequest(string requestCont // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(sampleInputInt.ToString(), await response.Content.ReadAsStringAsync()); + Assert.Equal(sampleInputInt.ToString(CultureInfo.InvariantCulture), await response.Content.ReadAsStringAsync()); } [Theory] @@ -63,7 +64,7 @@ public async Task JsonInputFormatter_IsModelStateValid_ForValidContentType( // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(expectedSampleIntValue.ToString(), responseBody); + Assert.Equal(expectedSampleIntValue.ToString(CultureInfo.InvariantCulture), responseBody); } [Theory] @@ -222,7 +223,7 @@ public async Task JsonInputFormatter_IsModelStateValid_ForTransferEncodingChunk( // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(expectedSampleIntValue.ToString(), responseBody); + Assert.Equal(expectedSampleIntValue.ToString(CultureInfo.InvariantCulture), responseBody); } } } \ No newline at end of file diff --git a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs index 3fcb25f6fbce..c424088ed5e3 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs @@ -55,7 +55,7 @@ public async Task Page_SimpleForms_RenderAntiforgery() responseContent = responseContent.Replace(forgeryToken, "{0}"); ResourceFile.UpdateFile(_resourcesAssembly, outputFile, expectedContent, responseContent); #else - expectedContent = string.Format(expectedContent, forgeryToken); + expectedContent = string.Format(CultureInfo.InvariantCulture, expectedContent, forgeryToken); Assert.Equal(expectedContent, responseContent, ignoreLineEndingDifferences: true); #endif } @@ -790,7 +790,7 @@ public async Task PolymorphicPropertiesOnPageModelsAreBound() Content = new FormUrlEncodedContent(new Dictionary { { "Name", name }, - { "Age", age.ToString() }, + { "Age", age.ToString(CultureInfo.InvariantCulture) }, }), }; await AddAntiforgeryHeaders(request); @@ -815,7 +815,7 @@ public async Task PolymorphicPropertiesOnPageModelsAreValidated() Content = new FormUrlEncodedContent(new Dictionary { { "Name", name }, - { "Age", age.ToString() }, + { "Age", age.ToString(CultureInfo.InvariantCulture) }, }), }; await AddAntiforgeryHeaders(request); diff --git a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs index 6318eb76ea7d..bebb9bae2d8a 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesWithBasePathTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Globalization; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -197,7 +198,7 @@ public async Task FormTagHelper_WithPageHandler_AllowsPostingToSelf() // Assert var responseContent = response.Trim(); var forgeryToken = AntiforgeryTestHelper.RetrieveAntiforgeryToken(responseContent, "/TagHelper/PostWithHandler"); - var expectedContent = string.Format(expected, forgeryToken); + var expectedContent = string.Format(CultureInfo.InvariantCulture, expected, forgeryToken); Assert.Equal(expectedContent, responseContent, ignoreLineEndingDifferences: true); } diff --git a/src/Mvc/test/Mvc.FunctionalTests/TagHelpersTest.cs b/src/Mvc/test/Mvc.FunctionalTests/TagHelpersTest.cs index 8f8adcefba76..d5c9889c02ec 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/TagHelpersTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/TagHelpersTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Globalization; using System.Net; using System.Net.Http; using System.Net.Http.Headers; @@ -127,7 +128,7 @@ public async Task ReRegisteringAntiforgeryTokenInsideFormTagHelper_DoesNotAddDup responseContent = responseContent.Replace(forgeryToken, "{0}"); ResourceFile.UpdateFile(_resourcesAssembly, outputFile, expectedContent, responseContent); #else - expectedContent = string.Format(expectedContent, forgeryToken); + expectedContent = string.Format(CultureInfo.InvariantCulture, expectedContent, forgeryToken); Assert.Equal( expectedContent.Trim(), responseContent, diff --git a/src/Mvc/test/Mvc.FunctionalTests/XmlDataContractSerializerInputFormatterTest.cs b/src/Mvc/test/Mvc.FunctionalTests/XmlDataContractSerializerInputFormatterTest.cs index 1b1b74a59183..2567b0a8d0d0 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/XmlDataContractSerializerInputFormatterTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/XmlDataContractSerializerInputFormatterTest.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; @@ -18,6 +19,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests public class XmlDataContractSerializerInputFormatterTest : IClassFixture> { private readonly string errorMessageFormat = string.Format( + CultureInfo.CurrentCulture, "{{1}}:{0} does not recognize '{1}', so instead use '{2}' with '{3}' set to '{4}' for value " + "type property '{{0}}' on type '{{1}}'.", typeof(DataContractSerializer).FullName, diff --git a/src/Mvc/test/Mvc.FunctionalTests/XmlSerializerInputFormatterTests.cs b/src/Mvc/test/Mvc.FunctionalTests/XmlSerializerInputFormatterTests.cs index 826905b7908c..5f4e41ab37a8 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/XmlSerializerInputFormatterTests.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/XmlSerializerInputFormatterTests.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using System.Net; using System.Net.Http; using System.Text; @@ -26,7 +27,7 @@ public async Task CheckIfXmlSerializerInputFormatterIsCalled() var sampleInputInt = 10; var input = "" + "" - + sampleInputInt.ToString() + ""; + + sampleInputInt.ToString(CultureInfo.InvariantCulture) + ""; var content = new StringContent(input, Encoding.UTF8, "application/xml-xmlser"); // Act @@ -34,7 +35,7 @@ public async Task CheckIfXmlSerializerInputFormatterIsCalled() // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(sampleInputInt.ToString(), await response.Content.ReadAsStringAsync()); + Assert.Equal(sampleInputInt.ToString(CultureInfo.InvariantCulture), await response.Content.ReadAsStringAsync()); } [ConditionalFact] diff --git a/src/Mvc/test/Mvc.IntegrationTests/ActionParametersIntegrationTest.cs b/src/Mvc/test/Mvc.IntegrationTests/ActionParametersIntegrationTest.cs index 99d82b9b719c..0a88723edf16 100644 --- a/src/Mvc/test/Mvc.IntegrationTests/ActionParametersIntegrationTest.cs +++ b/src/Mvc/test/Mvc.IntegrationTests/ActionParametersIntegrationTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Globalization; using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -408,6 +409,7 @@ public async Task ActionParameter_ModelPropertyTypeWithNoParameterlessConstructo var exception = await Assert.ThrowsAsync(() => parameterBinder.BindModelAsync(parameter, testContext)); Assert.Equal( string.Format( + CultureInfo.CurrentCulture, "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + "value types and must have a parameterless constructor. Record types must have a single primary constructor. " + "Alternatively, set the '{1}' property to a non-null value in the '{2}' constructor.", @@ -474,6 +476,7 @@ public async Task ActionParameter_UsingComplexTypeModelBinder_ModelPropertyTypeW var exception = await Assert.ThrowsAsync(() => parameterBinder.BindModelAsync(parameter, testContext)); Assert.Equal( string.Format( + CultureInfo.CurrentCulture, "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + "value types and must have a parameterless constructor. Alternatively, set the '{1}' property to" + " a non-null value in the '{2}' constructor.", @@ -500,6 +503,7 @@ public async Task ActionParameter_BindingToStructModel_ThrowsException() var exception = await Assert.ThrowsAsync(() => parameterBinder.BindModelAsync(parameter, testContext)); Assert.Equal( string.Format( + CultureInfo.CurrentCulture, "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + "value types and must have a parameterless constructor. Record types must have a single primary constructor.", typeof(PointStruct).FullName), @@ -522,6 +526,7 @@ public async Task ActionParameter_BindingToAbstractionType_ThrowsException() var exception = await Assert.ThrowsAsync(() => parameterBinder.BindModelAsync(parameter, testContext)); Assert.Equal( string.Format( + CultureInfo.CurrentCulture, "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + "value types and must have a parameterless constructor. Record types must have a single primary constructor.", typeof(AbstractClassWithNoDefaultConstructor).FullName), @@ -560,10 +565,11 @@ public async Task ActionParameter_MultipleConstructorsWithDefaultValues_NoParame var exception = await Assert.ThrowsAsync(() => parameterBinder.BindModelAsync(parameter, testContext)); Assert.Equal( string.Format( - "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + - "value types and must have a parameterless constructor. Record types must have a single primary constructor.", - typeof(ActionParameter_MultipleConstructorsWithDefaultValues_NoParameterlessConstructorModel).FullName), - exception.Message); + CultureInfo.CurrentCulture, + "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + + "value types and must have a parameterless constructor. Record types must have a single primary constructor.", + typeof(ActionParameter_MultipleConstructorsWithDefaultValues_NoParameterlessConstructorModel).FullName), + exception.Message); } public record ActionParameter_RecordTypeWithMultipleConstructors(string Name, int Age) @@ -592,6 +598,7 @@ public async Task ActionParameter_RecordTypeWithMultipleConstructors_Throws() var exception = await Assert.ThrowsAsync(() => parameterBinder.BindModelAsync(parameter, testContext)); Assert.Equal( string.Format( + CultureInfo.CurrentCulture, "Could not create an instance of type '{0}'. Model bound complex types must not be abstract or " + "value types and must have a parameterless constructor. Record types must have a single primary constructor.", typeof(ActionParameter_RecordTypeWithMultipleConstructors).FullName), @@ -719,7 +726,7 @@ public async Task ActionParameter_EnforcesBindRequired(int? input, bool isValid) { if (input.HasValue) { - request.QueryString = QueryString.Create(parameter.Name, input.Value.ToString()); + request.QueryString = QueryString.Create(parameter.Name, input.Value.ToString(CultureInfo.InvariantCulture)); } }); diff --git a/src/Mvc/test/Mvc.IntegrationTests/HeaderModelBinderIntegrationTest.cs b/src/Mvc/test/Mvc.IntegrationTests/HeaderModelBinderIntegrationTest.cs index a5440e5de2d0..c83c7eadcf79 100644 --- a/src/Mvc/test/Mvc.IntegrationTests/HeaderModelBinderIntegrationTest.cs +++ b/src/Mvc/test/Mvc.IntegrationTests/HeaderModelBinderIntegrationTest.cs @@ -508,7 +508,7 @@ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceT public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { var id = value.ToString(); - return new OrderWithTypeConverter() { Id = int.Parse(id) }; + return new OrderWithTypeConverter() { Id = int.Parse(id, CultureInfo.InvariantCulture) }; } } } diff --git a/src/Mvc/test/WebSites/BasicWebSite/Areas/Area2/Controllers/RemoteAttribute_VerifyController.cs b/src/Mvc/test/WebSites/BasicWebSite/Areas/Area2/Controllers/RemoteAttribute_VerifyController.cs index 9762d64c33d6..65cca2586051 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/Areas/Area2/Controllers/RemoteAttribute_VerifyController.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/Areas/Area2/Controllers/RemoteAttribute_VerifyController.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Microsoft.AspNetCore.Mvc; using BasicWebSite.Models; @@ -15,6 +16,7 @@ public class RemoteAttribute_VerifyController : Controller public IActionResult IsIdAvailable(RemoteAttributeUser user) { return new JsonResult(value: string.Format( + CultureInfo.InvariantCulture, "/Area2/RemoteAttribute_Verify/IsIdAvailable rejects '{0}' with '{1}', '{2}', and '{3}'.", user.UserId4, user.UserId1, diff --git a/src/Mvc/test/WebSites/BasicWebSite/Controllers/TempDataController.cs b/src/Mvc/test/WebSites/BasicWebSite/Controllers/TempDataController.cs index 1adeb1922a38..0753a3221af7 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/Controllers/TempDataController.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/Controllers/TempDataController.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Threading.Tasks; using BasicWebSite.Filters; using Microsoft.AspNetCore.Http; @@ -73,11 +74,11 @@ public async Task SetTempDataResponseWrite() public string GetTempDataMultiple() { var value1 = TempData["key1"].ToString(); - var value2 = Convert.ToInt32(TempData["key2"]); + var value2 = Convert.ToInt32(TempData["key2"], CultureInfo.InvariantCulture); var value3 = (IList)TempData["key3"]; var value4 = (DateTime)TempData["key4"]; var value5 = (Guid)TempData["key5"]; - return $"{value1} {value2.ToString()} {value3.Count.ToString()} {value4.ToString()} {value5.ToString()}"; + return $"{value1} {value2} {value3.Count} {value4} {value5}"; } [HttpGet] diff --git a/src/Mvc/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V3.cs b/src/Mvc/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V3.cs index 731e4dd0b2a1..96b8471e35b9 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V3.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V3.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -34,7 +35,7 @@ public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext co var builder = new StringBuilder(); builder.AppendLine("BEGIN:VCARD"); - builder.AppendFormat("FN:{0}", contact.Name); + builder.AppendFormat(CultureInfo.InvariantCulture, "FN:{0}", contact.Name); builder.AppendLine(); builder.AppendLine("END:VCARD"); diff --git a/src/Mvc/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V4.cs b/src/Mvc/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V4.cs index be5d28cfacef..25a0f166573d 100644 --- a/src/Mvc/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V4.cs +++ b/src/Mvc/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V4.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -35,9 +36,9 @@ public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext co var builder = new StringBuilder(); builder.AppendLine("BEGIN:VCARD"); - builder.AppendFormat("FN:{0}", contact.Name); + builder.AppendFormat(CultureInfo.InvariantCulture, "FN:{0}", contact.Name); builder.AppendLine(); - builder.AppendFormat("GENDER:{0}", (contact.Gender == GenderType.Male) ? "M" : "F"); + builder.AppendFormat(CultureInfo.InvariantCulture, "GENDER:{0}", (contact.Gender == GenderType.Male) ? "M" : "F"); builder.AppendLine(); builder.AppendLine("END:VCARD"); diff --git a/src/Mvc/test/WebSites/ControllersFromServicesWebSite/TagHelpers/InServicesTagHelper.cs b/src/Mvc/test/WebSites/ControllersFromServicesWebSite/TagHelpers/InServicesTagHelper.cs index 7fa57a1e7bde..778bb1724d9a 100644 --- a/src/Mvc/test/WebSites/ControllersFromServicesWebSite/TagHelpers/InServicesTagHelper.cs +++ b/src/Mvc/test/WebSites/ControllersFromServicesWebSite/TagHelpers/InServicesTagHelper.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Microsoft.AspNetCore.Razor.TagHelpers; namespace ControllersFromServicesWebSite.TagHelpers @@ -18,7 +19,7 @@ public InServicesTagHelper(ValueService value) public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = null; - output.Content.SetContent(_value.Value.ToString()); + output.Content.SetContent(_value.Value.ToString(CultureInfo.InvariantCulture)); } } } diff --git a/src/Mvc/test/WebSites/FormatterWebSite/Controllers/HomeController.cs b/src/Mvc/test/WebSites/FormatterWebSite/Controllers/HomeController.cs index 4258cac15331..885374699480 100644 --- a/src/Mvc/test/WebSites/FormatterWebSite/Controllers/HomeController.cs +++ b/src/Mvc/test/WebSites/FormatterWebSite/Controllers/HomeController.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -11,7 +12,7 @@ public class HomeController : Controller [HttpPost] public IActionResult Index([FromBody]DummyClass dummyObject) { - return Content(dummyObject.SampleInt.ToString()); + return Content(dummyObject.SampleInt.ToString(CultureInfo.InvariantCulture)); } [HttpPost] @@ -37,7 +38,7 @@ public DummyClass GetDerivedDummyClass(int sampleInput) } [HttpPost] - public IActionResult DefaultBody([FromBody] DummyClass dummy) + public IActionResult DefaultBody([FromBody] DummyClass dummy) => ModelState.IsValid ? Ok() : ValidationProblem(); [HttpPost] diff --git a/src/Mvc/test/WebSites/FormatterWebSite/Controllers/JsonFormatterController.cs b/src/Mvc/test/WebSites/FormatterWebSite/Controllers/JsonFormatterController.cs index 7732292b37fb..07ae37feaf83 100644 --- a/src/Mvc/test/WebSites/FormatterWebSite/Controllers/JsonFormatterController.cs +++ b/src/Mvc/test/WebSites/FormatterWebSite/Controllers/JsonFormatterController.cs @@ -4,6 +4,7 @@ using System; using System.Buffers; using System.ComponentModel.DataAnnotations; +using System.Globalization; using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -54,7 +55,7 @@ public IActionResult ReturnInput([FromBody] DummyClass dummyObject) return BadRequest(ModelState); } - return Content(dummyObject.SampleInt.ToString()); + return Content(dummyObject.SampleInt.ToString(CultureInfo.InvariantCulture)); } [HttpPost] @@ -65,7 +66,7 @@ public IActionResult ValueTypeAsBody([FromBody] int value) Response.StatusCode = StatusCodes.Status400BadRequest; } - return Content(value.ToString()); + return Content(value.ToString(CultureInfo.InvariantCulture)); } [HttpPost] diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/PolymorphicModelBinder.cs b/src/Mvc/test/WebSites/RazorPagesWebSite/PolymorphicModelBinder.cs index bce3d79b8a9c..fcdd15075196 100644 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/PolymorphicModelBinder.cs +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/PolymorphicModelBinder.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -14,7 +15,7 @@ public Task BindModelAsync(ModelBindingContext bindingContext) var age = 0; if (ageValue.Length != 0) { - age = int.Parse(ageValue.FirstValue); + age = int.Parse(ageValue.FirstValue, CultureInfo.InvariantCulture); } diff --git a/src/Mvc/test/WebSites/RoutingWebSite/TestParameterTransformer.cs b/src/Mvc/test/WebSites/RoutingWebSite/TestParameterTransformer.cs index a1aa4088f6ae..4721f4f17938 100644 --- a/src/Mvc/test/WebSites/RoutingWebSite/TestParameterTransformer.cs +++ b/src/Mvc/test/WebSites/RoutingWebSite/TestParameterTransformer.cs @@ -12,7 +12,7 @@ public class SlugifyParameterTransformer : IOutboundParameterTransformer public string TransformOutbound(object value) { // Slugify value - return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2", RegexOptions.None, TimeSpan.FromMilliseconds(100)).ToLower(); + return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2", RegexOptions.None, TimeSpan.FromMilliseconds(100)).ToLowerInvariant(); } } } \ No newline at end of file diff --git a/src/Mvc/test/WebSites/TagHelpersWebSite/Components/DanViewComponent.cs b/src/Mvc/test/WebSites/TagHelpersWebSite/Components/DanViewComponent.cs index 30f2d2d5e304..d23997fca79b 100644 --- a/src/Mvc/test/WebSites/TagHelpersWebSite/Components/DanViewComponent.cs +++ b/src/Mvc/test/WebSites/TagHelpersWebSite/Components/DanViewComponent.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Mvc; namespace TagHelpersWebSite @@ -10,7 +11,7 @@ public class DanViewComponent : ViewComponent { public IViewComponentResult Invoke(JacketColor jacketColor) { - var colorReplacement = string.Format("#", jacketColor); + var colorReplacement = string.Format(CultureInfo.InvariantCulture, "#", jacketColor); var resultString = DanString .Replace("#", colorReplacement) diff --git a/src/Mvc/test/WebSites/TagHelpersWebSite/TagHelpers/WebsiteInformationTagHelper.cs b/src/Mvc/test/WebSites/TagHelpersWebSite/TagHelpers/WebsiteInformationTagHelper.cs index b1a7ee746143..5a71299064b3 100644 --- a/src/Mvc/test/WebSites/TagHelpersWebSite/TagHelpers/WebsiteInformationTagHelper.cs +++ b/src/Mvc/test/WebSites/TagHelpersWebSite/TagHelpers/WebsiteInformationTagHelper.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Razor.TagHelpers; using TagHelpersWebSite.Models; @@ -15,14 +16,15 @@ public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "section"; output.PostContent.AppendHtml(string.Format( + CultureInfo.InvariantCulture, "

Version: {0}

" + Environment.NewLine + "

Copyright Year: {1}

" + Environment.NewLine + "

Approved: {2}

" + Environment.NewLine + "

Number of tags to show: {3}

" + Environment.NewLine, - Info.Version.ToString(), - Info.CopyrightYear.ToString(), - Info.Approved.ToString(), - Info.TagsToShow.ToString())); + Info.Version, + Info.CopyrightYear, + Info.Approved, + Info.TagsToShow)); output.TagMode = TagMode.StartTagAndEndTag; } } diff --git a/src/Mvc/test/WebSites/VersioningWebSite/VersionRouteAttribute.cs b/src/Mvc/test/WebSites/VersioningWebSite/VersionRouteAttribute.cs index e12ec2d805f4..1a5123b47d1f 100644 --- a/src/Mvc/test/WebSites/VersioningWebSite/VersionRouteAttribute.cs +++ b/src/Mvc/test/WebSites/VersioningWebSite/VersionRouteAttribute.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Text.RegularExpressions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ActionConstraints; @@ -40,7 +41,7 @@ public VersionRouteAttribute(string template, string versionRange) if (constraint == null) { - var message = string.Format("Invalid version format: {0}", versionRange); + var message = $"Invalid version format: {versionRange}"; throw new ArgumentException(message, "versionRange"); } @@ -82,8 +83,8 @@ private static IActionConstraint GetBoundedRangeVersionConstraint( return null; } - var minVersion = int.Parse(rangeValues[0]); - var maxVersion = int.Parse(rangeValues[1]); + var minVersion = int.Parse(rangeValues[0], CultureInfo.InvariantCulture); + var maxVersion = int.Parse(rangeValues[1], CultureInfo.InvariantCulture); // Adjust min version and max version if the limit is exclusive. minVersion = lowerBound == "(" ? minVersion + 1 : minVersion; @@ -109,7 +110,7 @@ private static IActionConstraint GetSingleVersionOrUnboundedHigherVersionConstra return null; } - var version = int.Parse(rangeValues[0]); + var version = int.Parse(rangeValues[0], CultureInfo.InvariantCulture); if (!string.IsNullOrEmpty(lowerBound)) { // [5] diff --git a/src/Mvc/test/WebSites/XmlFormattersWebSite/Controllers/HomeController.cs b/src/Mvc/test/WebSites/XmlFormattersWebSite/Controllers/HomeController.cs index 9cf910399dc3..97db10c12597 100644 --- a/src/Mvc/test/WebSites/XmlFormattersWebSite/Controllers/HomeController.cs +++ b/src/Mvc/test/WebSites/XmlFormattersWebSite/Controllers/HomeController.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -21,7 +22,7 @@ public IActionResult Index([FromBody]DummyClass dummyObject) }; } - return Content(dummyObject.SampleInt.ToString()); + return Content(dummyObject.SampleInt.ToString(CultureInfo.InvariantCulture)); } // Cannot use 'SerializableError' here as it sanitizes exceptions in model state with generic error message. diff --git a/src/Mvc/test/WebSites/XmlFormattersWebSite/Controllers/ValidationController.cs b/src/Mvc/test/WebSites/XmlFormattersWebSite/Controllers/ValidationController.cs index e5d4b6862f20..8553aaaefa87 100644 --- a/src/Mvc/test/WebSites/XmlFormattersWebSite/Controllers/ValidationController.cs +++ b/src/Mvc/test/WebSites/XmlFormattersWebSite/Controllers/ValidationController.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Globalization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -49,7 +50,7 @@ private List GetModelStateErrorMessages(ModelStateDictionary modelStateD if (errorMessage != null) { - allErrorMessages.Add(string.Format("{0}:{1}", key, errorMessage)); + allErrorMessages.Add(string.Format(CultureInfo.InvariantCulture, "{0}:{1}", key, errorMessage)); } } } diff --git a/src/Mvc/test/WebSites/XmlFormattersWebSite/PersonWrapper.cs b/src/Mvc/test/WebSites/XmlFormattersWebSite/PersonWrapper.cs index 81740545a588..d7f30f151b11 100644 --- a/src/Mvc/test/WebSites/XmlFormattersWebSite/PersonWrapper.cs +++ b/src/Mvc/test/WebSites/XmlFormattersWebSite/PersonWrapper.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using XmlFormattersWebSite.Models; using Microsoft.AspNetCore.Mvc.Formatters.Xml; @@ -26,7 +27,7 @@ public PersonWrapper(Person person) public override string ToString() { - return string.Format("{0}, {1}, {2}", Id, Name, Age); + return string.Format(CultureInfo.InvariantCulture, "{0}, {1}, {2}", Id, Name, Age); } public object Unwrap(Type declaredType) diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs index 7a47f9b84acf..f4c12288dbe2 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs @@ -198,7 +198,7 @@ private void TestBasicNavigation() [InlineData("SingleOrg", new string[] { "--calls-graph" })] public async Task BlazorServerTemplat_IdentityWeb_BuildAndPublish(string auth, string[] args) { - Project = await ProjectFactory.GetOrCreateProject("blazorserveridweb" + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output); + Project = await ProjectFactory.GetOrCreateProject("blazorserveridweb" + Guid.NewGuid().ToString().Substring(0, 10).ToLowerInvariant(), Output); var createResult = await Project.RunDotNetNewAsync("blazorserver", auth: auth, args: args); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", Project, createResult)); diff --git a/src/ProjectTemplates/Shared/AspNetProcess.cs b/src/ProjectTemplates/Shared/AspNetProcess.cs index 13a9281c5620..11da0c3fcc81 100644 --- a/src/ProjectTemplates/Shared/AspNetProcess.cs +++ b/src/ProjectTemplates/Shared/AspNetProcess.cs @@ -174,7 +174,7 @@ public async Task ContainsLinks(Page page) IHtmlAnchorElement anchor = (IHtmlAnchorElement)link; if (string.Equals(anchor.Protocol, "about:")) { - Assert.True(anchor.PathName.EndsWith(expectedLink), $"Expected next link on {page.Url} to be {expectedLink} but it was {anchor.PathName}."); + Assert.True(anchor.PathName.EndsWith(expectedLink, StringComparison.Ordinal), $"Expected next link on {page.Url} to be {expectedLink} but it was {anchor.PathName}."); await AssertOk(anchor.PathName); } else diff --git a/src/ProjectTemplates/Shared/Project.cs b/src/ProjectTemplates/Shared/Project.cs index e1ce4b2a4164..748cd875800b 100644 --- a/src/ProjectTemplates/Shared/Project.cs +++ b/src/ProjectTemplates/Shared/Project.cs @@ -252,7 +252,7 @@ internal async Task RunDotNetEfUpdateDatabaseAsync() public void AssertEmptyMigration(string migration) { var fullPath = Path.Combine(TemplateOutputDir, "Data/Migrations"); - var file = Directory.EnumerateFiles(fullPath).Where(f => f.EndsWith($"{migration}.cs")).FirstOrDefault(); + var file = Directory.EnumerateFiles(fullPath).Where(f => f.EndsWith($"{migration}.cs", StringComparison.Ordinal)).FirstOrDefault(); Assert.NotNull(file); var contents = File.ReadAllText(file); diff --git a/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs b/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs index c029db07e092..83d0c85e1aba 100644 --- a/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs +++ b/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs @@ -32,11 +32,13 @@ internal static class TemplatePackageInstaller "Microsoft.DotNet.Web.ProjectTemplates.3.0", "Microsoft.DotNet.Web.ProjectTemplates.3.1", "Microsoft.DotNet.Web.ProjectTemplates.5.0", + "Microsoft.DotNet.Web.ProjectTemplates.6.0", "Microsoft.DotNet.Web.Spa.ProjectTemplates.2.1", "Microsoft.DotNet.Web.Spa.ProjectTemplates.2.2", "Microsoft.DotNet.Web.Spa.ProjectTemplates.3.0", "Microsoft.DotNet.Web.Spa.ProjectTemplates.3.1", "Microsoft.DotNet.Web.Spa.ProjectTemplates.5.0", + "Microsoft.DotNet.Web.Spa.ProjectTemplates.6.0", "Microsoft.DotNet.Web.Spa.ProjectTemplates", "Microsoft.AspNetCore.Blazor.Templates", }; @@ -129,7 +131,7 @@ NUnit 3 Test Item (nunit-test) VB foreach (var command in lines.Where(l => l.Contains("dotnet new") && l.Contains(packageName, StringComparison.OrdinalIgnoreCase))) { var uninstallCommand = command.TrimStart(); - Debug.Assert(uninstallCommand.StartsWith("dotnet new")); + Debug.Assert(uninstallCommand.StartsWith("dotnet new", StringComparison.Ordinal)); uninstallCommand = uninstallCommand.Substring("dotnet new".Length); await RunDotNetNew(output, uninstallCommand); } diff --git a/src/ProjectTemplates/Shared/TestOutputLogger.cs b/src/ProjectTemplates/Shared/TestOutputLogger.cs index b01edf2e7bd8..5f69b7928da6 100644 --- a/src/ProjectTemplates/Shared/TestOutputLogger.cs +++ b/src/ProjectTemplates/Shared/TestOutputLogger.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Microsoft.Extensions.Logging; using Xunit.Abstractions; @@ -22,7 +23,7 @@ public void WriteLine(string message) public void WriteLine(string format, params object[] args) { - _logger.LogInformation(string.Format(format, args)); + _logger.LogInformation(string.Format(CultureInfo.InvariantCulture, format, args)); } } } diff --git a/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj b/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj index 5b39b0fd0d85..396b74c39690 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj +++ b/src/ProjectTemplates/Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj @@ -2,7 +2,7 @@ $(DefaultNetCoreTargetFramework) - Microsoft.DotNet.Web.ProjectTemplates.$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + Microsoft.DotNet.Web.ProjectTemplates.$(AspNetCoreMajorMinorVersion) ASP.NET Core Web Template Pack for Microsoft Template Engine $(RepoRoot)src\Components\WebAssembly\ diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj b/src/ProjectTemplates/Web.Spa.ProjectTemplates/Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj index 62e1c07e7db8..e9341c91b1f9 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj @@ -2,7 +2,7 @@ $(DefaultNetCoreTargetFramework) - Microsoft.DotNet.Web.Spa.ProjectTemplates.$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion) + Microsoft.DotNet.Web.Spa.ProjectTemplates.$(AspNetCoreMajorMinorVersion) Single Page Application templates for ASP.NET Core $(PackageTags);spa diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.ts b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.ts index d1fa469908f5..5853edff2442 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.ts +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login-menu/login-menu.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { AuthorizeService } from '../authorize.service'; import { Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; @Component({ selector: 'app-login-menu', diff --git a/src/ProjectTemplates/scripts/Run-Angular-Locally.ps1 b/src/ProjectTemplates/scripts/Run-Angular-Locally.ps1 index ec8993da7ea1..3724496d4097 100644 --- a/src/ProjectTemplates/scripts/Run-Angular-Locally.ps1 +++ b/src/ProjectTemplates/scripts/Run-Angular-Locally.ps1 @@ -9,4 +9,4 @@ $ErrorActionPreference = 'Stop' . $PSScriptRoot\Test-Template.ps1 -Test-Template "angular" "angular" "Microsoft.DotNet.Web.Spa.ProjectTemplates.5.0.5.0.0-dev.nupkg" $true +Test-Template "angular" "angular" "Microsoft.DotNet.Web.Spa.ProjectTemplates.6.0.6.0.0-dev.nupkg" $true diff --git a/src/ProjectTemplates/scripts/Run-Blazor-Locally.ps1 b/src/ProjectTemplates/scripts/Run-Blazor-Locally.ps1 index 575036e9c7ac..7a510a7a9a45 100644 --- a/src/ProjectTemplates/scripts/Run-Blazor-Locally.ps1 +++ b/src/ProjectTemplates/scripts/Run-Blazor-Locally.ps1 @@ -10,4 +10,4 @@ $ErrorActionPreference = 'Stop' . $PSScriptRoot\Test-Template.ps1 -Test-Template "blazorserver" "blazorserver" "Microsoft.DotNet.Web.ProjectTemplates.5.0.5.0.0-dev.nupkg" $false +Test-Template "blazorserver" "blazorserver" "Microsoft.DotNet.Web.ProjectTemplates.6.0.6.0.0-dev.nupkg" $false diff --git a/src/ProjectTemplates/scripts/Run-EmptyWeb-Locally.ps1 b/src/ProjectTemplates/scripts/Run-EmptyWeb-Locally.ps1 index d6859c6f7278..10e743504b58 100644 --- a/src/ProjectTemplates/scripts/Run-EmptyWeb-Locally.ps1 +++ b/src/ProjectTemplates/scripts/Run-EmptyWeb-Locally.ps1 @@ -9,4 +9,4 @@ $ErrorActionPreference = 'Stop' . $PSScriptRoot\Test-Template.ps1 -Test-Template "web" "web" "Microsoft.DotNet.Web.ProjectTemplates.5.0.5.0.0-dev.nupkg" $false +Test-Template "web" "web" "Microsoft.DotNet.Web.ProjectTemplates.6.0.6.0.0-dev.nupkg" $false diff --git a/src/ProjectTemplates/scripts/Run-Razor-Locally.ps1 b/src/ProjectTemplates/scripts/Run-Razor-Locally.ps1 index ecba4fbd8fc1..6f16590be8fe 100644 --- a/src/ProjectTemplates/scripts/Run-Razor-Locally.ps1 +++ b/src/ProjectTemplates/scripts/Run-Razor-Locally.ps1 @@ -6,4 +6,4 @@ param() . $PSScriptRoot\Test-Template.ps1 -Test-Template "webapp" "webapp -au Individual" "Microsoft.DotNet.Web.ProjectTemplates.5.0.5.0.0-dev.nupkg" $false +Test-Template "webapp" "webapp -au Individual" "Microsoft.DotNet.Web.ProjectTemplates.6.0.6.0.0-dev.nupkg" $false diff --git a/src/ProjectTemplates/scripts/Run-React-Locally.ps1 b/src/ProjectTemplates/scripts/Run-React-Locally.ps1 index 8308860edccf..f69f07a20d24 100644 --- a/src/ProjectTemplates/scripts/Run-React-Locally.ps1 +++ b/src/ProjectTemplates/scripts/Run-React-Locally.ps1 @@ -9,4 +9,4 @@ $ErrorActionPreference = 'Stop' . $PSScriptRoot\Test-Template.ps1 -Test-Template "react" "react" "Microsoft.DotNet.Web.Spa.ProjectTemplates.5.0.5.0.0-dev.nupkg" $true +Test-Template "react" "react" "Microsoft.DotNet.Web.Spa.ProjectTemplates.6.0.6.0.0-dev.nupkg" $true diff --git a/src/ProjectTemplates/scripts/Run-ReactRedux-Locally.ps1 b/src/ProjectTemplates/scripts/Run-ReactRedux-Locally.ps1 index 6100d7cacd13..0eda170ab13e 100644 --- a/src/ProjectTemplates/scripts/Run-ReactRedux-Locally.ps1 +++ b/src/ProjectTemplates/scripts/Run-ReactRedux-Locally.ps1 @@ -9,4 +9,4 @@ $ErrorActionPreference = 'Stop' . $PSScriptRoot\Test-Template.ps1 -Test-Template "reactredux" "reactredux" "Microsoft.DotNet.Web.Spa.ProjectTemplates.5.0.5.0.0-dev.nupkg" $true +Test-Template "reactredux" "reactredux" "Microsoft.DotNet.Web.Spa.ProjectTemplates.6.0.6.0.0-dev.nupkg" $true diff --git a/src/ProjectTemplates/scripts/Run-Starterweb-Locally.ps1 b/src/ProjectTemplates/scripts/Run-Starterweb-Locally.ps1 index 61ad47fbdcfd..ab195cd016ef 100644 --- a/src/ProjectTemplates/scripts/Run-Starterweb-Locally.ps1 +++ b/src/ProjectTemplates/scripts/Run-Starterweb-Locally.ps1 @@ -9,4 +9,4 @@ $ErrorActionPreference = 'Stop' . $PSScriptRoot\Test-Template.ps1 -Test-Template "mvc" "mvc -au Individual" "Microsoft.DotNet.Web.ProjectTemplates.5.0.5.0.0-dev.nupkg" $false +Test-Template "mvc" "mvc -au Individual" "Microsoft.DotNet.Web.ProjectTemplates.6.0.6.0.0-dev.nupkg" $false diff --git a/src/ProjectTemplates/scripts/Run-Worker-Locally.ps1 b/src/ProjectTemplates/scripts/Run-Worker-Locally.ps1 index e6ff856e7e77..9f3c0272096d 100644 --- a/src/ProjectTemplates/scripts/Run-Worker-Locally.ps1 +++ b/src/ProjectTemplates/scripts/Run-Worker-Locally.ps1 @@ -9,4 +9,4 @@ $ErrorActionPreference = 'Stop' . $PSScriptRoot\Test-Template.ps1 -Test-Template "worker" "worker" "Microsoft.DotNet.Web.ProjectTemplates.5.0.5.0.0-dev.nupkg" $false +Test-Template "worker" "worker" "Microsoft.DotNet.Web.ProjectTemplates.6.0.6.0.0-dev.nupkg" $false diff --git a/src/ProjectTemplates/test/BaselineTest.cs b/src/ProjectTemplates/test/BaselineTest.cs index 23e9320ec7ff..baddc80f8991 100644 --- a/src/ProjectTemplates/test/BaselineTest.cs +++ b/src/ProjectTemplates/test/BaselineTest.cs @@ -81,7 +81,6 @@ public ITestOutputHelper Output [Theory] [MemberData(nameof(TemplateBaselines))] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23993")] public async Task Template_Produces_The_Right_Set_Of_FilesAsync(string arguments, string[] expectedFiles) { Project = await ProjectFactory.GetOrCreateProject("baseline" + SanitizeArgs(arguments), Output); diff --git a/src/ProjectTemplates/test/EmptyWebTemplateTest.cs b/src/ProjectTemplates/test/EmptyWebTemplateTest.cs index ada7b31fac44..e96a713c28f1 100644 --- a/src/ProjectTemplates/test/EmptyWebTemplateTest.cs +++ b/src/ProjectTemplates/test/EmptyWebTemplateTest.cs @@ -32,7 +32,7 @@ public ITestOutputHelper Output } [ConditionalFact] - [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("Cert failures", Queues = "All.OSX")] public async Task EmptyWebTemplateCSharp() { await EmtpyTemplateCore(languageOverride: null); diff --git a/src/ProjectTemplates/test/GrpcTemplateTest.cs b/src/ProjectTemplates/test/GrpcTemplateTest.cs index f5a9b73064f1..d05f3aacebce 100644 --- a/src/ProjectTemplates/test/GrpcTemplateTest.cs +++ b/src/ProjectTemplates/test/GrpcTemplateTest.cs @@ -33,7 +33,7 @@ public ITestOutputHelper Output } [ConditionalFact] - [SkipOnHelix("Not supported queues", Queues = "Windows.7.Amd64;Windows.7.Amd64.Open;Windows.81.Amd64.Open;OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("Not supported queues", Queues = "Windows.7.Amd64;Windows.7.Amd64.Open;Windows.81.Amd64.Open;All.OSX")] public async Task GrpcTemplate() { var project = await ProjectFactory.GetOrCreateProject("grpc", Output); diff --git a/src/ProjectTemplates/test/IdentityUIPackageTest.cs b/src/ProjectTemplates/test/IdentityUIPackageTest.cs index 94c569496efa..d5fb7b859463 100644 --- a/src/ProjectTemplates/test/IdentityUIPackageTest.cs +++ b/src/ProjectTemplates/test/IdentityUIPackageTest.cs @@ -74,8 +74,7 @@ public ITestOutputHelper Output }; [ConditionalFact] - [SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/19716")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/26776")] public async Task IdentityUIPackage_WorksWithDifferentOptions() { var packageOptions = new Dictionary(); diff --git a/src/ProjectTemplates/test/MvcTemplateTest.cs b/src/ProjectTemplates/test/MvcTemplateTest.cs index 649286396976..bfc402ccd2f3 100644 --- a/src/ProjectTemplates/test/MvcTemplateTest.cs +++ b/src/ProjectTemplates/test/MvcTemplateTest.cs @@ -40,7 +40,7 @@ public ITestOutputHelper Output public async Task MvcTemplate_NoAuthFSharp() => await MvcTemplateCore(languageOverride: "F#"); [ConditionalFact] - [SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("cert failure", Queues = "All.OSX")] public async Task MvcTemplate_NoAuthCSharp() => await MvcTemplateCore(languageOverride: null); private async Task MvcTemplateCore(string languageOverride) @@ -118,7 +118,7 @@ private async Task MvcTemplateCore(string languageOverride) [ConditionalTheory] [InlineData(true)] [InlineData(false)] - [SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/26776")] public async Task MvcTemplate_IndividualAuth(bool useLocalDB) { var project = await ProjectFactory.GetOrCreateProject("mvcindividual" + (useLocalDB ? "uld" : ""), Output); @@ -146,6 +146,7 @@ public async Task MvcTemplate_IndividualAuth(bool useLocalDB) Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", project, migrationsResult)); project.AssertEmptyMigration("mvc"); + // Note: if any links are updated here, RazorPagesTemplateTest.cs should be updated as well var pages = new List { new Page { @@ -234,7 +235,7 @@ public async Task MvcTemplate_IndividualAuth(bool useLocalDB) } [ConditionalFact(Skip = "https://github.com/dotnet/aspnetcore/issues/25103")] - [SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("cert failure", Queues = "All.OSX")] public async Task MvcTemplate_SingleFileExe() { // This test verifies publishing an MVC app as a single file exe works. We'll limit testing @@ -323,7 +324,7 @@ public async Task MvcTemplate_RazorRuntimeCompilation_BuildsAndPublishes() private async Task MvcTemplateBuildsAndPublishes(string auth, string[] args) { - var project = await ProjectFactory.GetOrCreateProject("mvc" + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output); + var project = await ProjectFactory.GetOrCreateProject("mvc" + Guid.NewGuid().ToString().Substring(0, 10).ToLowerInvariant(), Output); var createResult = await project.RunDotNetNewAsync("mvc", auth: auth, args: args); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult)); diff --git a/src/ProjectTemplates/test/RazorPagesTemplateTest.cs b/src/ProjectTemplates/test/RazorPagesTemplateTest.cs index 919f410f0f61..6dbdcf63e1ee 100644 --- a/src/ProjectTemplates/test/RazorPagesTemplateTest.cs +++ b/src/ProjectTemplates/test/RazorPagesTemplateTest.cs @@ -35,7 +35,7 @@ public ITestOutputHelper Output } [ConditionalFact] - [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("Cert failures", Queues = "All.OSX")] public async Task RazorPagesTemplate_NoAuth() { var project = await ProjectFactory.GetOrCreateProject("razorpagesnoauth", Output); @@ -106,8 +106,7 @@ public async Task RazorPagesTemplate_NoAuth() [ConditionalTheory] [InlineData(false)] [InlineData(true)] - [SkipOnHelix("cert failure", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/19716")] + [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/26776")] public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) { var project = await ProjectFactory.GetOrCreateProject("razorpagesindividual" + (useLocalDB ? "uld" : ""), Output); @@ -135,16 +134,17 @@ public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) Assert.True(0 == migrationsResult.ExitCode, ErrorMessages.GetFailedProcessMessage("run EF migrations", project, migrationsResult)); project.AssertEmptyMigration("razorpages"); + // Note: if any links are updated here, MvcTemplateTest.cs should be updated as well var pages = new List { new Page { Url = PageUrls.ForgotPassword, Links = new string [] { PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, PageUrls.HomeUrl, PageUrls.PrivacyUrl, + PageUrls.RegisterUrl, + PageUrls.LoginUrl, PageUrls.PrivacyUrl } }, @@ -153,10 +153,10 @@ public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) Url = PageUrls.HomeUrl, Links = new string[] { PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, PageUrls.HomeUrl, PageUrls.PrivacyUrl, + PageUrls.RegisterUrl, + PageUrls.LoginUrl, PageUrls.DocsUrl, PageUrls.PrivacyUrl } @@ -166,10 +166,10 @@ public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) Url = PageUrls.PrivacyUrl, Links = new string[] { PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, PageUrls.HomeUrl, PageUrls.PrivacyUrl, + PageUrls.RegisterUrl, + PageUrls.LoginUrl, PageUrls.PrivacyUrl } }, @@ -178,10 +178,10 @@ public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) Url = PageUrls.LoginUrl, Links = new string[] { PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, PageUrls.HomeUrl, PageUrls.PrivacyUrl, + PageUrls.RegisterUrl, + PageUrls.LoginUrl, PageUrls.ForgotPassword, PageUrls.RegisterUrl, PageUrls.ResendEmailConfirmation, @@ -193,10 +193,10 @@ public async Task RazorPagesTemplate_IndividualAuth(bool useLocalDB) Url = PageUrls.RegisterUrl, Links = new string [] { PageUrls.HomeUrl, - PageUrls.RegisterUrl, - PageUrls.LoginUrl, PageUrls.HomeUrl, PageUrls.PrivacyUrl, + PageUrls.RegisterUrl, + PageUrls.LoginUrl, PageUrls.ExternalArticle, PageUrls.PrivacyUrl } @@ -244,7 +244,7 @@ public async Task RazorPagesTemplate_RazorRuntimeCompilation_BuildsAndPublishes( private async Task BuildAndPublishRazorPagesTemplate(string auth, string[] args) { - var project = await ProjectFactory.GetOrCreateProject("razorpages" + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output); + var project = await ProjectFactory.GetOrCreateProject("razorpages" + Guid.NewGuid().ToString().Substring(0, 10).ToLowerInvariant(), Output); var createResult = await project.RunDotNetNewAsync("razor", auth: auth, args: args); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult)); diff --git a/src/ProjectTemplates/test/WebApiTemplateTest.cs b/src/ProjectTemplates/test/WebApiTemplateTest.cs index 5e18beaf0381..b8be8444c434 100644 --- a/src/ProjectTemplates/test/WebApiTemplateTest.cs +++ b/src/ProjectTemplates/test/WebApiTemplateTest.cs @@ -44,11 +44,11 @@ public ITestOutputHelper Output public Task WebApiTemplateFSharp() => WebApiTemplateCore(languageOverride: "F#"); [ConditionalFact] - [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("Cert failures", Queues = "All.OSX")] public Task WebApiTemplateCSharp() => WebApiTemplateCore(languageOverride: null); [ConditionalFact] - [SkipOnHelix("Cert failures", Queues = "OSX.1014.Amd64;OSX.1014.Amd64.Open")] + [SkipOnHelix("Cert failures", Queues = "All.OSX")] public async Task WebApiTemplateCSharp_WithoutOpenAPI() { var project = await FactoryFixture.GetOrCreateProject("webapinoopenapi", Output); @@ -69,7 +69,7 @@ public async Task WebApiTemplateCSharp_WithoutOpenAPI() private async Task PublishAndBuildWebApiTemplate(string languageOverride, string auth, string[] args) { - var project = await FactoryFixture.GetOrCreateProject("webapi" + (languageOverride == "F#" ? "fsharp" : "csharp") + Guid.NewGuid().ToString().Substring(0, 10).ToLower(), Output); + var project = await FactoryFixture.GetOrCreateProject("webapi" + (languageOverride == "F#" ? "fsharp" : "csharp") + Guid.NewGuid().ToString().Substring(0, 10).ToLowerInvariant(), Output); var createResult = await project.RunDotNetNewAsync("webapi", language: languageOverride, auth: auth, args: args); Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult)); diff --git a/src/ProjectTemplates/test/WorkerTemplateTest.cs b/src/ProjectTemplates/test/WorkerTemplateTest.cs index 0b04d17c6d79..fca3e8c10879 100644 --- a/src/ProjectTemplates/test/WorkerTemplateTest.cs +++ b/src/ProjectTemplates/test/WorkerTemplateTest.cs @@ -34,6 +34,7 @@ public ITestOutputHelper Output [OSSkipCondition(OperatingSystems.Linux, SkipReason = "https://github.com/dotnet/sdk/issues/12831")] [InlineData("C#")] [InlineData("F#")] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/25404")] public async Task WorkerTemplateAsync(string language) { var project = await ProjectFactory.GetOrCreateProject( diff --git a/src/ProjectTemplates/test/template-baselines.json b/src/ProjectTemplates/test/template-baselines.json index ac99c7a49167..9e36b3eed22e 100644 --- a/src/ProjectTemplates/test/template-baselines.json +++ b/src/ProjectTemplates/test/template-baselines.json @@ -915,6 +915,7 @@ "Data/Migrations/ApplicationDbContextModelSnapshot.cs", "Pages/Counter.razor", "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", @@ -954,6 +955,7 @@ "Data/WeatherForecastService.cs", "Pages/Counter.razor", "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", @@ -993,6 +995,7 @@ "Data/WeatherForecastService.cs", "Pages/Counter.razor", "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", @@ -1031,6 +1034,7 @@ "Data/WeatherForecast.cs", "Data/WeatherForecastService.cs", "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", "Pages/Counter.razor", "Pages/FetchData.razor", "Pages/Index.razor", @@ -1070,6 +1074,7 @@ "Data/WeatherForecastService.cs", "Pages/Counter.razor", "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", @@ -1109,6 +1114,7 @@ "Data/WeatherForecastService.cs", "Pages/Counter.razor", "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", "Pages/FetchData.razor", "Pages/Index.razor", "Pages/_Host.cshtml", diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/src/MvcViewDocumentClassifierPass.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/src/MvcViewDocumentClassifierPass.cs index b4a5c930f6a0..bcfc120e781e 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/src/MvcViewDocumentClassifierPass.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/src/MvcViewDocumentClassifierPass.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Text; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Intermediate; @@ -62,7 +63,7 @@ private static string BytesToString(byte[] bytes) for (var i = 0; i < bytes.Length; i++) { // The x2 format means lowercase hex, where each byte is a 2-character string. - result.Append(bytes[i].ToString("x2")); + result.Append(bytes[i].ToString("x2", CultureInfo.InvariantCulture)); } return result.ToString(); diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/InstrumentationPass.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/InstrumentationPass.cs index f82ed32e4563..f10aeb9707a5 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/InstrumentationPass.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/InstrumentationPass.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; @@ -40,7 +40,9 @@ private static void AddInstrumentation(InstrumentationItem item) beginNode.Children.Add(new IntermediateToken() { Kind = TokenKind.CSharp, - Content = string.Format("{0}({1}, {2}, {3});", + Content = string.Format( + CultureInfo.InvariantCulture, + "{0}({1}, {2}, {3});", beginContextMethodName, item.Source.AbsoluteIndex.ToString(CultureInfo.InvariantCulture), item.Source.Length.ToString(CultureInfo.InvariantCulture), @@ -51,7 +53,7 @@ private static void AddInstrumentation(InstrumentationItem item) endNode.Children.Add(new IntermediateToken() { Kind = TokenKind.CSharp, - Content = string.Format("{0}();", endContextMethodName) + Content = string.Format(CultureInfo.InvariantCulture, "{0}();", endContextMethodName) }); var nodeIndex = item.Parent.Children.IndexOf(item.Node); diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/MvcViewDocumentClassifierPass.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/MvcViewDocumentClassifierPass.cs index 7ec6a1360e76..813dd2db4a12 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/MvcViewDocumentClassifierPass.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/MvcViewDocumentClassifierPass.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Text; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Intermediate; @@ -62,7 +63,7 @@ private static string BytesToString(byte[] bytes) for (var i = 0; i < bytes.Length; i++) { // The x2 format means lowercase hex, where each byte is a 2-character string. - result.Append(bytes[i].ToString("x2")); + result.Append(bytes[i].ToString("x2", CultureInfo.InvariantCulture)); } return result.ToString(); diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/RazorPageDocumentClassifierPass.cs b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/RazorPageDocumentClassifierPass.cs index b11912ff8128..dbda9500fcc3 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/RazorPageDocumentClassifierPass.cs +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/src/RazorPageDocumentClassifierPass.cs @@ -1,8 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Diagnostics; +using System.Globalization; using System.Text; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Extensions; @@ -155,7 +156,7 @@ private static string BytesToString(byte[] bytes) for (var i = 0; i < bytes.Length; i++) { // The x2 format means lowercase hex, where each byte is a 2-character string. - result.Append(bytes[i].ToString("x2")); + result.Append(bytes[i].ToString("x2", CultureInfo.InvariantCulture)); } return result.ToString(); diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AttributeDirectiveWithViewImports_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AttributeDirectiveWithViewImports_DesignTime.codegen.html index e2017f6ce6f8..672af16a9f7d 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AttributeDirectiveWithViewImports_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AttributeDirectiveWithViewImports_DesignTime.codegen.html @@ -1 +1 @@ - \ No newline at end of file +~~~~~~~~~~ ~~~~~~~~~~~~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent_DesignTime.codegen.html index e7b0219a389d..212a52af7b23 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/BasicComponent_DesignTime.codegen.html @@ -1,9 +1,9 @@ - -
+~~~~~~~~~~~ ~~~~~~~~~~~ +
Hello world - + ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~
- - - +~~~~~~~~~~ ~ + ~~~~ ~~~~~~~~~~~~~~~~~~~~~~ ~ +~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_DesignTime.codegen.html index 08d042e89793..1d05c8edd11c 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Basic_DesignTime.codegen.html @@ -1,8 +1,8 @@ -
+
Hello world - + ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~
- - - -

+~~ + ~~~ ~~~ ~ ~~~~~~ +~ +

diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.html index 85fabc0abd8a..41bd21fb73e0 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.html @@ -1,15 +1,15 @@ - +~~ ~~~~~ ~~~~ ~~~~~ ~~~~~~~~ ~~~~ ~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~ ~~~~~~ ~~ - - - " +~~~~~ +~~~~~ +~~~~~ " - - +~~~~~~ +~~~~~~ - - - +~~~~~~~ +~~~~~~~ +~~~~~~~ ~~~~~~~~~~~~~~~~~ - - +~~~~~~~~~~ +~~~~~~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InheritsViewModel_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InheritsViewModel_DesignTime.codegen.html index 6adf1586e10f..7c8f96178083 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InheritsViewModel_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InheritsViewModel_DesignTime.codegen.html @@ -1,2 +1,2 @@ - - +~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~ ~~~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InheritsWithViewImports_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InheritsWithViewImports_DesignTime.codegen.html index b1214751a93b..cc39225641f6 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InheritsWithViewImports_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InheritsWithViewImports_DesignTime.codegen.html @@ -1,2 +1,2 @@ - - +~~~~~ +~~~~~~ ~~~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InjectWithModel_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InjectWithModel_DesignTime.codegen.html index b05e435fdae9..b9ccc4dd9435 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InjectWithModel_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InjectWithModel_DesignTime.codegen.html @@ -1,3 +1,3 @@ - - - +~~~~~~ ~~~~~~~ +~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~ +~~~~~~~ ~~~~~~~~~~~~~~~~~ ~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InjectWithSemicolon_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InjectWithSemicolon_DesignTime.codegen.html index 0c20f0ce0ce5..6b3f658f9627 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InjectWithSemicolon_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InjectWithSemicolon_DesignTime.codegen.html @@ -1,5 +1,5 @@ - - - - - +~~~~~~ ~~~~~~~ +~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~~ +~~~~~~~ ~~~~~~~~~~~~~~~~~ ~~~~~ +~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~~ ~ +~~~~~~~ ~~~~~~~~~~~~~~~~~ ~~~~~ ~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Inject_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Inject_DesignTime.codegen.html index 8a218bdd8dad..579717aaec4e 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Inject_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Inject_DesignTime.codegen.html @@ -1 +1 @@ - +~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.codegen.html index c72931e132ba..8a36a67848ae 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InvalidNamespaceAtEOF_DesignTime.codegen.html @@ -1 +1 @@ - Test. \ No newline at end of file +~~~~~~~~~~ Test. \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.codegen.html index 9645bac584dd..ef573d0f478c 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MalformedPageDirective_DesignTime.codegen.html @@ -1,4 +1,4 @@ - "foo +~~~~~ "foo

About Us

We are awesome.

\ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ModelExpressionTagHelper_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ModelExpressionTagHelper_DesignTime.codegen.html index 4649d9d2d64b..0109819d0a0f 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ModelExpressionTagHelper_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ModelExpressionTagHelper_DesignTime.codegen.html @@ -1,6 +1,6 @@ - +~~~~~~ ~~~~~~~~ - +~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~ - - + + diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Model_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Model_DesignTime.codegen.html index 1638a82fb44c..9eb7434ef14a 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Model_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Model_DesignTime.codegen.html @@ -1 +1 @@ - +~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MultipleModels_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MultipleModels_DesignTime.codegen.html index 4a2f4743cfc7..338f2c39940e 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MultipleModels_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MultipleModels_DesignTime.codegen.html @@ -1,2 +1,2 @@ - - +~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ +~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PageWithNamespace_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PageWithNamespace_DesignTime.codegen.html index 6742b0a9e33d..f3527d34b88c 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PageWithNamespace_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/PageWithNamespace_DesignTime.codegen.html @@ -1,3 +1,3 @@ - - +~~~~~ +~~~~~~~~~~ ~~~~~~~~~~~~~~

Hi There!

diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.codegen.html index 8f9ba3e6233b..e1debaeb457f 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPageWithNoLeadingPageDirective_DesignTime.codegen.html @@ -1,2 +1,2 @@
Some text here.
- +~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPagesWithRouteTemplate_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPagesWithRouteTemplate_DesignTime.codegen.html index dbfd76ba01f2..6ea17442f79b 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPagesWithRouteTemplate_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPagesWithRouteTemplate_DesignTime.codegen.html @@ -1,13 +1,13 @@ - +~~~~~ ~~~~~~~~ - - +~~~~~~ ~~~~~~~~ +~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - - - +~~~~~~~~~~ ~ + ~~~~~~ ~~~~~ ~~~~~~~~ ~ ~~~~~~~~~ + ~ + ~~~~~~ ~~~~~~ ~~~~ ~ ~~~~ ~~~~ ~ + ~ +~ -

New Customer

+

New Customer ~~~~~~~~~~~

diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPagesWithoutModel_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPagesWithoutModel_DesignTime.codegen.html index ae827b127094..1788ff55ca6f 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPagesWithoutModel_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPagesWithoutModel_DesignTime.codegen.html @@ -1,28 +1,28 @@ - +~~~~~ - - +~~~~~~~~~~~~~ ~~~ ~~~~~~~~ +~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - - - +~~~~~~~~~~ ~ + ~~~~~~ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ ~~~~~~~~~ + ~ + ~~~~ ~ ~~~~~~~~~~~~~~ + ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ - + ~~~~~~ ~~~~~~ ~~~~ ~ ~~~~ ~~~~ ~ - - - - - + ~~~~~~ ~~~~~ ~~~~~~~~ + ~ + ~~~~~~ ~~~~~~ ~~~~ ~ ~~~~ ~~~~ ~ + ~ +~

New Customer

- +
diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPages_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPages_DesignTime.codegen.html index dc0c2ec4e1b7..3bc18cff89a6 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPages_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorPages_DesignTime.codegen.html @@ -1,32 +1,32 @@ - +~~~~~ - - - +~~~~~~ ~~~~~~~~ +~~~~~~~~~~~~~ ~~~ ~~~~~~~~ +~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - - - - - +~~~~~~~~~~ ~ + ~~~~~~ ~~~~~ ~~~~~~~~ ~ ~~~~~~~~~ + ~ + ~~~~~~ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ ~~~~~~~~~ + ~ + ~~~~ ~ ~~~~~~~~~~~~~~ + ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ - - + ~~~~~~ ~~~~~~ ~~~~ ~ ~~~~ ~~~~ ~ + ~ - - - - - + ~~~~~~ ~~~~~ ~~~~~~~~ + ~ + ~~~~~~ ~~~~~~ ~~~~ ~ ~~~~ ~~~~ ~ + ~ +~

New Customer

- +
diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections_DesignTime.codegen.html index 849f18b01572..1dc5378382f5 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections_DesignTime.codegen.html @@ -1,14 +1,14 @@ - +~~~~~~ ~~~~~~~~ - +~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~ - - - +~~ + ~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~
Some body
- +~~~~~~~~ ~~~~~~~~ ~
This is in Section 1
- - \ No newline at end of file + +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/UsingDirectives_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/UsingDirectives_DesignTime.codegen.html index 52fe51a13096..38bab0bda99b 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/UsingDirectives_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/UsingDirectives_DesignTime.codegen.html @@ -1,4 +1,4 @@ - - - - \ No newline at end of file +~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ +~~~~~~ ~~~~~~~~~~~~~~~~~~ +~~~~~~ ~~~~~~ +~~~~~~ ~~~~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ViewComponentTagHelper_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ViewComponentTagHelper_DesignTime.codegen.html index 5b456be824f8..e3c647d97a4f 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ViewComponentTagHelper_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ViewComponentTagHelper_DesignTime.codegen.html @@ -1,6 +1,6 @@ - - - - +~~~~~~~~~~~~~ ~~~ ~~~~~~~~ +~~ + ~~~ ~~~ ~ ~~~~~~~~ +~ - \ No newline at end of file + \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ViewWithNamespace_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ViewWithNamespace_DesignTime.codegen.html index 835b3a68caea..30c2f53307d5 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ViewWithNamespace_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ViewWithNamespace_DesignTime.codegen.html @@ -1,2 +1,2 @@ - +~~~~~~~~~~ ~~~~~~~~~~~~~~

Hi There!

diff --git a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/_ViewImports_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/_ViewImports_DesignTime.codegen.html index 262e601e9cc7..f53681d3d2e4 100644 --- a/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/_ViewImports_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/_ViewImports_DesignTime.codegen.html @@ -1 +1 @@ - \ No newline at end of file +~~~~~~~ ~~~~~~~~~~~~~~~~~~~ ~~~~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/BoundAttributeDescriptorBuilderExtensions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/BoundAttributeDescriptorBuilderExtensions.cs index ac01e48aa1c9..ba565acf2dfa 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/BoundAttributeDescriptorBuilderExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/BoundAttributeDescriptorBuilderExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/BoundAttributeDescriptorExtensions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/BoundAttributeDescriptorExtensions.cs index 9ea08e85371e..8542e4a6338a 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/BoundAttributeDescriptorExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/BoundAttributeDescriptorExtensions.cs @@ -84,4 +84,4 @@ public static string GetPropertyName(this BoundAttributeParameterDescriptor para return propertyName; } } -} \ No newline at end of file +} diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Checksum.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Checksum.cs index 57834739e6c9..ca862c5441d3 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Checksum.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Checksum.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Text; namespace Microsoft.AspNetCore.Razor.Language @@ -19,7 +20,7 @@ public static string BytesToString(byte[] bytes) for (var i = 0; i < bytes.Length; i++) { // The x2 format means lowercase hex, where each byte is a 2-character string. - result.Append(bytes[i].ToString("x2")); + result.Append(bytes[i].ToString("x2", CultureInfo.InvariantCulture)); } return result.ToString(); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs index 005941d9156f..eeb14f021887 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentRuntimeNodeWriter.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Text; using Microsoft.AspNetCore.Razor.Language.CodeGeneration; @@ -99,7 +100,7 @@ public override void WriteCSharpExpression(CodeRenderingContext context, CSharpE // text to display context.CodeWriter .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddContent}") - .Write((_sourceSequence++).ToString()) + .Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator(); for (var i = 0; i < node.Children.Count; i++) @@ -159,7 +160,7 @@ public override void WriteMarkupBlock(CodeRenderingContext context, MarkupBlockI context.CodeWriter .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddMarkupContent}") - .Write((_sourceSequence++).ToString()) + .Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator() .WriteStringLiteral(node.Content) .WriteEndMethodInvocation(); @@ -179,7 +180,7 @@ public override void WriteMarkupElement(CodeRenderingContext context, MarkupElem context.CodeWriter .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.OpenElement}") - .Write((_sourceSequence++).ToString()) + .Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator() .WriteStringLiteral(node.TagName) .WriteEndMethodInvocation(); @@ -295,7 +296,7 @@ public override void WriteHtmlContent(CodeRenderingContext context, HtmlContentI context.CodeWriter .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{renderApi}") - .Write((_sourceSequence++).ToString()) + .Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator() .WriteStringLiteral(content) .WriteEndMethodInvocation(); @@ -359,7 +360,7 @@ public override void WriteComponent(CodeRenderingContext context, ComponentInter context.CodeWriter.Write("<"); context.CodeWriter.Write(node.TypeName); context.CodeWriter.Write(">("); - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.Write(");"); context.CodeWriter.WriteLine(); @@ -427,12 +428,12 @@ public override void WriteComponent(CodeRenderingContext context, ComponentInter context.CodeWriter.Write(_scopeStack.BuilderVarName); context.CodeWriter.Write(", "); - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.Write(", "); for (var i = 0; i < attributes.Count; i++) { - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.Write(", "); // Don't type check generics, since we can't actually write the type name. @@ -456,7 +457,7 @@ public override void WriteComponent(CodeRenderingContext context, ComponentInter for (var i = 0; i < childContents.Count; i++) { - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.Write(", "); WriteComponentChildContentInnards(context, childContents[i]); @@ -470,7 +471,7 @@ public override void WriteComponent(CodeRenderingContext context, ComponentInter for (var i = 0; i < setKeys.Count; i++) { - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.Write(", "); WriteSetKeyInnards(context, setKeys[i]); @@ -484,7 +485,7 @@ public override void WriteComponent(CodeRenderingContext context, ComponentInter for (var i = 0; i < captures.Count; i++) { - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.Write(", "); WriteReferenceCaptureInnards(context, captures[i], shouldTypeCheck: false); @@ -520,7 +521,7 @@ public override void WriteComponentAttribute(CodeRenderingContext context, Compo context.CodeWriter.Write("."); context.CodeWriter.Write(addAttributeMethod); context.CodeWriter.Write("("); - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.Write(", "); context.CodeWriter.WriteStringLiteral(node.AttributeName); context.CodeWriter.Write(", "); @@ -768,7 +769,7 @@ public override void WriteSplat(CodeRenderingContext context, SplatIntermediateN // // _builder.AddMultipleAttributes(2, ...); context.CodeWriter.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddMultipleAttributes}"); - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.WriteParameterSeparator(); WriteSplatInnards(context, node, canTypeCheck: true); @@ -814,7 +815,7 @@ public override void WriteReferenceCapture(CodeRenderingContext context, Referen : ComponentsApi.RenderTreeBuilder.AddElementReferenceCapture; codeWriter .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{methodName}") - .Write((_sourceSequence++).ToString()) + .Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator(); WriteReferenceCaptureInnards(context, node, shouldTypeCheck: true); @@ -884,7 +885,7 @@ protected override void BeginWriteAttribute(CodeRenderingContext context, string { context.CodeWriter .WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddAttribute}") - .Write((_sourceSequence++).ToString()) + .Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)) .WriteParameterSeparator() .WriteStringLiteral(key); } @@ -892,7 +893,7 @@ protected override void BeginWriteAttribute(CodeRenderingContext context, string protected override void BeginWriteAttribute(CodeRenderingContext context, IntermediateNode nameExpression) { context.CodeWriter.WriteStartMethodInvocation($"{_scopeStack.BuilderVarName}.{ComponentsApi.RenderTreeBuilder.AddAttribute}"); - context.CodeWriter.Write((_sourceSequence++).ToString()); + context.CodeWriter.Write((_sourceSequence++).ToString(CultureInfo.InvariantCulture)); context.CodeWriter.WriteParameterSeparator(); var tokens = GetCSharpTokens(nameExpression); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorSourceLineCollection.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorSourceLineCollection.cs index 42767671c0fb..482d88624f09 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorSourceLineCollection.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorSourceLineCollection.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -38,7 +38,7 @@ public override int GetLineLength(int index) internal override SourceLocation GetLocation(int position) { - if (position < 0 || position >= _document.Length) + if (position < 0 || position > _document.Length) { throw new IndexOutOfRangeException(nameof(position)); } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/TagHelperParseTreeRewriter.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/TagHelperParseTreeRewriter.cs index 25e191a36987..e04178acf9a1 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/TagHelperParseTreeRewriter.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Legacy/TagHelperParseTreeRewriter.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -163,7 +163,7 @@ public override SyntaxNode VisitMarkupElement(MarkupElementSyntax node) if (endTag != null) { var tagName = endTag.GetTagNameWithOptionalBang(); - if (TryRewriteTagHelperEnd(endTag, out tagHelperEnd)) + if (TryRewriteTagHelperEnd(startTag, endTag, out tagHelperEnd)) { // This is a tag helper if (startTag == null) @@ -289,10 +289,10 @@ private bool TryRewriteTagHelperStart( return true; } - private bool TryRewriteTagHelperEnd(MarkupEndTagSyntax tagBlock, out MarkupTagHelperEndTagSyntax rewritten) + private bool TryRewriteTagHelperEnd(MarkupStartTagSyntax startTag, MarkupEndTagSyntax endTag, out MarkupTagHelperEndTagSyntax rewritten) { rewritten = null; - var tagName = tagBlock.GetTagNameWithOptionalBang(); + var tagName = endTag.GetTagNameWithOptionalBang(); // Could not determine tag name, it can't be a TagHelper, continue on and track the element. if (string.IsNullOrEmpty(tagName) || tagName.StartsWith("!")) { @@ -301,13 +301,13 @@ private bool TryRewriteTagHelperEnd(MarkupEndTagSyntax tagBlock, out MarkupTagHe var tracker = CurrentTagHelperTracker; var tagNameScope = tracker?.TagName ?? string.Empty; - if (!IsPotentialTagHelperEnd(tagName, tagBlock)) + if (!IsPotentialTagHelperEnd(tagName, endTag)) { return false; } // Validate that our end tag matches the currently scoped tag, if not we may need to error. - if (tagNameScope.Equals(tagName, StringComparison.OrdinalIgnoreCase)) + if (startTag != null && tagNameScope.Equals(tagName, StringComparison.OrdinalIgnoreCase)) { // If there are additional end tags required before we can build our block it means we're in a // situation like this: where we're at the inside . @@ -318,7 +318,7 @@ private bool TryRewriteTagHelperEnd(MarkupEndTagSyntax tagBlock, out MarkupTagHe return false; } - ValidateEndTagSyntax(tagName, tagBlock); + ValidateEndTagSyntax(tagName, endTag); _trackerStack.Pop(); } @@ -347,7 +347,7 @@ private bool TryRewriteTagHelperEnd(MarkupEndTagSyntax tagBlock, out MarkupTagHe // End tag TagHelper that states it shouldn't have an end tag. _errorSink.OnError( RazorDiagnosticFactory.CreateParsing_TagHelperMustNotHaveAnEndTag( - new SourceSpan(SourceLocationTracker.Advance(tagBlock.GetSourceLocation(_source), " FindHierarchicalItems(string basePa var fileNameIndex = path.LastIndexOf('/'); var length = path.Length; Debug.Assert(fileNameIndex != -1); - if (string.Compare(path, fileNameIndex + 1, fileName, 0, fileName.Length) == 0) + if (string.Compare(path, fileNameIndex + 1, fileName, 0, fileName.Length, StringComparison.Ordinal) == 0) { // If the specified path is for the file hierarchy being constructed, then the first file that applies // to it is in a parent directory. diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/GreenNode.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/GreenNode.cs index 3f03464510ea..cda914192d12 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/GreenNode.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/GreenNode.cs @@ -1,9 +1,10 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Linq; using System.Runtime.CompilerServices; @@ -256,7 +257,7 @@ internal SyntaxAnnotation[] GetAnnotations() public override string ToString() { var builder = new StringBuilder(); - builder.AppendFormat("{0}<{1}>", GetType().Name, Kind); + builder.AppendFormat(CultureInfo.InvariantCulture, "{0}<{1}>", GetType().Name, Kind); return builder.ToString(); } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxAnnotation.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxAnnotation.cs index e6393354757d..b2faf85832bd 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxAnnotation.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxAnnotation.cs @@ -1,8 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Diagnostics; +using System.Globalization; namespace Microsoft.AspNetCore.Razor.Language.Syntax { @@ -42,7 +43,7 @@ public SyntaxAnnotation(string kind, object data) private string GetDebuggerDisplay() { - return string.Format("Annotation: Kind='{0}' Data='{1}'", this.Kind ?? "", this.Data ?? ""); + return string.Format(CultureInfo.InvariantCulture, "Annotation: Kind='{0}' Data='{1}'", this.Kind ?? "", this.Data ?? ""); } public bool Equals(SyntaxAnnotation other) diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxExtensions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxExtensions.cs index 055180ca97db..f3ae1619d03f 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxExtensions.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxExtensions.cs @@ -1,13 +1,15 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; + namespace Microsoft.AspNetCore.Razor.Language.Syntax { internal partial class MarkupTextLiteralSyntax { protected override string GetDebuggerDisplay() { - return string.Format("{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); + return string.Format(CultureInfo.InvariantCulture, "{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); } } @@ -15,7 +17,7 @@ internal partial class MarkupEphemeralTextLiteralSyntax { protected override string GetDebuggerDisplay() { - return string.Format("{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); + return string.Format(CultureInfo.InvariantCulture, "{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); } } @@ -23,7 +25,7 @@ internal partial class CSharpStatementLiteralSyntax { protected override string GetDebuggerDisplay() { - return string.Format("{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); + return string.Format(CultureInfo.InvariantCulture, "{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); } } @@ -31,7 +33,7 @@ internal partial class CSharpExpressionLiteralSyntax { protected override string GetDebuggerDisplay() { - return string.Format("{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); + return string.Format(CultureInfo.InvariantCulture, "{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); } } @@ -39,7 +41,7 @@ internal partial class CSharpEphemeralTextLiteralSyntax { protected override string GetDebuggerDisplay() { - return string.Format("{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); + return string.Format(CultureInfo.InvariantCulture, "{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); } } @@ -47,7 +49,7 @@ internal partial class UnclassifiedTextLiteralSyntax { protected override string GetDebuggerDisplay() { - return string.Format("{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); + return string.Format(CultureInfo.InvariantCulture, "{0} [{1}]", base.GetDebuggerDisplay(), this.GetContent()); } } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxNode.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxNode.cs index aacc0eb91e3e..e02fe0e9f6cb 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxNode.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Syntax/SyntaxNode.cs @@ -1,9 +1,10 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Text; using System.Threading; @@ -419,7 +420,7 @@ public override string ToString() { var builder = new StringBuilder(); builder.Append(Green.ToString()); - builder.AppendFormat(" at {0}::{1}", Position, FullWidth); + builder.AppendFormat(CultureInfo.InvariantCulture, " at {0}::{1}", Position, FullWidth); return builder.ToString(); } @@ -433,10 +434,10 @@ protected virtual string GetDebuggerDisplay() { if (IsToken) { - return string.Format("{0};[{1}]", Kind, ToFullString()); + return string.Format(CultureInfo.InvariantCulture, "{0};[{1}]", Kind, ToFullString()); } - return string.Format("{0} [{1}..{2})", Kind, Position, EndPosition); + return string.Format(CultureInfo.InvariantCulture, "{0} [{1}..{2})", Kind, Position, EndPosition); } } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/RuntimeNodeWriterTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/RuntimeNodeWriterTest.cs index 666bdb649bc8..ac4843a7e33b 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/RuntimeNodeWriterTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/CodeGeneration/RuntimeNodeWriterTest.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Razor.Language.Intermediate; using Xunit; @@ -489,6 +490,7 @@ public void WriteHtmlContent_LargeStringLiteral_UsesMultipleWrites() // Assert var csharp = context.CodeWriter.GenerateCode(); Assert.Equal(string.Format( + CultureInfo.InvariantCulture, @"WriteLiteral(@""{0}""); WriteLiteral(@""{1}""); ", new string('*', 1024), new string('*', 976)), diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorDiagnosticTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorDiagnosticTest.cs index bf8f3099ce4b..90d7564bc25b 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorDiagnosticTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorDiagnosticTest.cs @@ -1,4 +1,4 @@ -// Copyright(c) .NET Foundation.All rights reserved. +// Copyright(c) .NET Foundation.All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -36,7 +36,7 @@ public void DefaultRazorDiagnostic_GetMessage() var diagnostic = new DefaultRazorDiagnostic(descriptor, span, new object[0]); // Act - var result = diagnostic.GetMessage(); + var result = diagnostic.GetMessage(CultureInfo.CurrentCulture); // Assert Assert.Equal("error", result); @@ -53,7 +53,7 @@ public void DefaultRazorDiagnostic_GetMessage_WithArgs() var diagnostic = new DefaultRazorDiagnostic(descriptor, span, new[] { "error" }); // Act - var result = diagnostic.GetMessage(); + var result = diagnostic.GetMessage(CultureInfo.CurrentCulture); // Assert Assert.Equal("this is an error", result); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorIntermediateNodeLoweringPhaseTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorIntermediateNodeLoweringPhaseTest.cs index 908983d50a54..9adb28946aa6 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorIntermediateNodeLoweringPhaseTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorIntermediateNodeLoweringPhaseTest.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Razor.Language.Intermediate; using Microsoft.AspNetCore.Testing; @@ -134,7 +135,7 @@ public void Execute_DoesNotImportNonFileScopedSinglyOccurringDirectives_Block() var options = RazorParserOptions.Create(builder => { builder.Directives.Add(codeBlockDirective); - builder.Directives.Add(razorBlockDirective); + builder.Directives.Add(razorBlockDirective); }); var importSource = TestRazorSourceDocument.Create( @"@code ""code block"" { } @@ -254,7 +255,7 @@ public void Execute_CollatesSyntaxDiagnosticsFromSourceDocument() var documentNode = codeDocument.GetDocumentIntermediateNode(); var diagnostic = Assert.Single(documentNode.Diagnostics); Assert.Equal(@"The explicit expression block is missing a closing "")"" character. Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] @@ -286,12 +287,12 @@ public void Execute_CollatesSyntaxDiagnosticsFromImportDocuments() diagnostic => { Assert.Equal(@"A space or line break was encountered after the ""@"" character. Only valid identifiers, keywords, comments, ""("" and ""{"" are valid at the start of a code block and they must occur immediately following ""@"" with no space in between.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); }, diagnostic => { Assert.Equal(@"The explicit expression block is missing a closing "")"" character. Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); }); } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorProjectFileSystemTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorProjectFileSystemTest.cs index a158f1dc8a02..29165b4cc7d3 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorProjectFileSystemTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorProjectFileSystemTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -264,7 +264,7 @@ public void GetItem_MismatchedCase_ReturnsFileFromDisk() { // Arrange var filePath = "/Views/About/About.cshtml"; - var lowerCaseTestFolder = TestFolder.ToLower(); + var lowerCaseTestFolder = TestFolder.ToLowerInvariant(); var fileSystem = new DefaultRazorProjectFileSystem(lowerCaseTestFolder); // Act diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorSourceLineCollectionTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorSourceLineCollectionTest.cs new file mode 100644 index 000000000000..748e195f9060 --- /dev/null +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/DefaultRazorSourceLineCollectionTest.cs @@ -0,0 +1,132 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Xunit; + +namespace Microsoft.AspNetCore.Razor.Language.Test +{ + public class DefaultRazorSourceLineCollectionTest + { + [Fact] + public void GetLocation_Negative() + { + // Arrange + var content = @"@addTagHelper, * Stuff +@* A comment *@"; + var document = TestRazorSourceDocument.Create(content); + var collection = new DefaultRazorSourceLineCollection(document); + + // Act & Assert + Assert.Throws(() => collection.GetLocation(-1)); + } + + [Fact] + public void GetLocation_TooBig() + { + // Arrange + var content = @"addTagHelper, * Stuff +@* A comment *@"; + var document = TestRazorSourceDocument.Create(content); + var collection = new DefaultRazorSourceLineCollection(document); + + // Act & Assert + Assert.Throws(() => collection.GetLocation(40)); + } + + [Fact] + public void GetLocation_AtStart() + { + // Arrange + var content = @"@addTaghelper, * Stuff +@* A comment *@"; + var document = TestRazorSourceDocument.Create(content); + var collection = new DefaultRazorSourceLineCollection(document); + + // Act + var location = collection.GetLocation(0); + + // Assert + var expected = new SourceLocation("test.cshtml", 0, 0, 0); + Assert.Equal(expected, location); + } + + [Fact] + public void GetLocation_AtEnd() + { + // Arrange + var content = @"@addTagHelper, * Stuff +@* A comment *@"; + var document = TestRazorSourceDocument.Create(content); + var collection = new DefaultRazorSourceLineCollection(document); + var length = content.Length; + + // Act + var location = collection.GetLocation(length); + + // Assert + var expected = new SourceLocation("test.cshtml", length, 1, 15); + Assert.Equal(expected, location); + } + + [Fact] + public void GetLineLength_Negative() + { + // Arrange + var content = @"@addTagHelper, * Stuff +@* A comment *@"; + var document = TestRazorSourceDocument.Create(content); + var collection = new DefaultRazorSourceLineCollection(document); + + // Act & Assert + Assert.Throws(() => collection.GetLineLength(-1)); + } + + [Fact] + public void GetLineLength_Bigger() + { + // Arrange + var content = @"@addTagHelper, * Stuff +@* A comment *@"; + var document = TestRazorSourceDocument.Create(content); + var collection = new DefaultRazorSourceLineCollection(document); + + // Act & Assert + Assert.Throws(() => collection.GetLineLength(40)); + } + + [Fact] + public void GetLineLength_AtStart() + { + // Arrange + var content = @"@addTagHelper, * Stuff +@* A comment *@"; + var document = TestRazorSourceDocument.Create(content); + var collection = new DefaultRazorSourceLineCollection(document); + + // Act + var lineLength = collection.GetLineLength(0); + + // Assert + var expectedLineLength = 22 + Environment.NewLine.Length; + Assert.Equal(expectedLineLength, lineLength); + } + + [Fact] + public void GetLineLength_AtEnd() + { + // Arrange + var content = @"@addTagHelper, * Stuff +@* A comment *@"; + var document = TestRazorSourceDocument.Create(content); + var collection = new DefaultRazorSourceLineCollection(document); + + // Act + var lineLength = collection.GetLineLength(1); + + // Assert + var expectedLineLength = 15; + Assert.Equal(expectedLineLength, lineLength); + } + } +} diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentBindIntegrationTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentBindIntegrationTest.cs index 77bd6c9ed31f..4896309a0ce3 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentBindIntegrationTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentBindIntegrationTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Components; using Xunit; @@ -44,7 +45,7 @@ public static class BindAttributes "The attribute '@bind-value' was matched by multiple bind attributes. Duplicates:" + Environment.NewLine + "Test.BindAttributes" + Environment.NewLine + "Test.BindAttributes", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentChildContentIntegrationTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentChildContentIntegrationTest.cs index 624de396b59b..f241a665afd0 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentChildContentIntegrationTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentChildContentIntegrationTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Razor.Language.Components; using Microsoft.CodeAnalysis.CSharp; @@ -143,7 +144,7 @@ public void ChildContent_ExplicitChildContent_UnrecogizedContent_ProducesDiagnos Assert.Equal( "Unrecognized child content inside component 'RenderChildContent'. The component 'RenderChildContent' accepts " + "child content through the following top-level items: 'ChildContent'.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] @@ -226,7 +227,7 @@ public void ChildContent_ExplicitChildContent_RepeatedParameterName_GeneratesDia Assert.Equal( "The child content element 'ChildContent' of component 'RenderChildContentString' uses the same parameter name ('context') as enclosing child content " + "element 'ChildContent' of component 'RenderChildContentString'. Specify the parameter name like: ' to resolve the ambiguity", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] @@ -245,7 +246,7 @@ public void ChildContent_ContextParameterNameOnComponent_Invalid_ProducesDiagnos Assert.Same(ComponentDiagnosticFactory.ChildContentHasInvalidParameterOnComponent.Id, diagnostic.Id); Assert.Equal( "Invalid parameter name. The parameter name attribute 'Context' on component 'RenderChildContentString' can only include literal text.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] @@ -266,7 +267,7 @@ public void ChildContent_ExplicitChildContent_ContainsDirectiveAttribute_Produce Assert.Same(ComponentDiagnosticFactory.ChildContentHasInvalidAttribute.Id, diagnostic.Id); Assert.Equal( "Unrecognized attribute '@key' on child content element 'ChildContent'.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentDiagnosticRazorIntegrationTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentDiagnosticRazorIntegrationTest.cs index 863e2a0d16ea..3f2c1c3d2de4 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentDiagnosticRazorIntegrationTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentDiagnosticRazorIntegrationTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Xunit; namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests @@ -23,7 +24,7 @@ public void RejectsEndTagWithNoStartTag() item => { Assert.Equal("RZ9981", item.Id); - Assert.Equal("Unexpected closing tag 'mytag' with no matching start tag.", item.GetMessage()); + Assert.Equal("Unexpected closing tag 'mytag' with no matching start tag.", item.GetMessage(CultureInfo.CurrentCulture)); }); } @@ -41,7 +42,7 @@ public void OldCodeBlockAttributeSyntax_ReportsError() // Assert var diagnostic = Assert.Single(generated.Diagnostics); Assert.Equal("RZ9979", diagnostic.Id); - Assert.NotNull(diagnostic.GetMessage()); + Assert.NotNull(diagnostic.GetMessage(CultureInfo.CurrentCulture)); } @@ -62,7 +63,7 @@ public void RejectsScriptTag() item => { Assert.Equal("RZ9992", item.Id); - Assert.Equal("Script tags should not be placed inside components because they cannot be updated dynamically. To fix this, move the script tag to the 'index.html' file or another static location. For more information see https://go.microsoft.com/fwlink/?linkid=872131", item.GetMessage()); + Assert.Equal("Script tags should not be placed inside components because they cannot be updated dynamically. To fix this, move the script tag to the 'index.html' file or another static location. For more information see https://go.microsoft.com/fwlink/?linkid=872131", item.GetMessage(CultureInfo.CurrentCulture)); Assert.Equal(2, item.Span.LineIndex); Assert.Equal(4, item.Span.CharacterIndex); }); @@ -96,7 +97,7 @@ @tagHelperPrefix th { Assert.Equal("RZ9978", item.Id); Assert.Equal("The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. " + - "Use '@using ' directive instead.", item.GetMessage()); + "Use '@using ' directive instead.", item.GetMessage(CultureInfo.CurrentCulture)); Assert.Equal(0, item.Span.LineIndex); Assert.Equal(0, item.Span.CharacterIndex); }, @@ -104,7 +105,7 @@ @tagHelperPrefix th { Assert.Equal("RZ9978", item.Id); Assert.Equal("The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. " + - "Use '@using ' directive instead.", item.GetMessage()); + "Use '@using ' directive instead.", item.GetMessage(CultureInfo.CurrentCulture)); Assert.Equal(1, item.Span.LineIndex); Assert.Equal(0, item.Span.CharacterIndex); }); @@ -125,7 +126,7 @@ public void DirectiveAttribute_ComplexContent_ReportsError() Assert.Equal("RZ9986", diagnostic.Id); Assert.Equal( "Component attributes do not support complex content (mixed C# and markup). Attribute: '@key', text: 'Foo @Text'", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] @@ -143,7 +144,7 @@ public void Component_StartsWithLowerCase_ReportsError() Assert.Equal("RZ10011", diagnostic.Id); Assert.Equal( "Component 'lowerCase' starts with a lowercase character. Component names cannot start with a lowercase character.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] @@ -163,7 +164,7 @@ public void Element_DoesNotStartWithLowerCase_ReportsWarning() Assert.Equal(RazorDiagnosticSeverity.Warning, diagnostic.Severity); Assert.Equal( "Found markup element with unexpected name 'PossibleComponent'. If this is intended to be a component, add a @using directive for its namespace.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] @@ -199,7 +200,7 @@ public class MyComponent : ComponentBase Assert.Equal("RZ10013", diagnostic.Id); Assert.Equal( "The start tag name 'MyComponent' does not match the end tag name 'mycomponent'. Components must have matching start and end tag names (case-sensitive).", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentGenericTypeIntegrationTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentGenericTypeIntegrationTest.cs index 70c936d13f66..d103cc7cf712 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentGenericTypeIntegrationTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentGenericTypeIntegrationTest.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Microsoft.AspNetCore.Razor.Language.Components; using Microsoft.CodeAnalysis.CSharp; using Xunit; @@ -95,7 +96,7 @@ public void GenericComponent_WithoutAnyTypeParameters_TriggersDiagnostic() Assert.Equal( "The type of component 'GenericContext' cannot be inferred based on the values provided. Consider " + "specifying the type arguments directly using the following attributes: 'TItem'.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } [Fact] @@ -114,7 +115,7 @@ public void GenericComponent_WithMissingTypeParameters_TriggersDiagnostic() Assert.Equal( "The component 'MultipleGenericParameter' is missing required type arguments. " + "Specify the missing types using the attributes: 'TItem2', 'TItem3'.", - diagnostic.GetMessage()); + diagnostic.GetMessage(CultureInfo.CurrentCulture)); } } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentImportsIntegrationTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentImportsIntegrationTest.cs index a4241730fe0e..4e14b42caff2 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentImportsIntegrationTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentImportsIntegrationTest.cs @@ -1,6 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Globalization; using Xunit; namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests @@ -63,7 +64,7 @@ public void ErrorsForPageDirective() item => { Assert.Equal("RZ9987", item.Id); - Assert.Equal(@"The '@page' directive specified in _Imports.razor file will not be imported. The directive must appear at the top of each Razor file", item.GetMessage()); + Assert.Equal(@"The '@page' directive specified in _Imports.razor file will not be imported. The directive must appear at the top of each Razor file", item.GetMessage(CultureInfo.CurrentCulture)); }); } @@ -83,19 +84,19 @@ public void ErrorsForTagHelperDirectives() { Assert.Equal("RZ9978", item.Id); Assert.Equal(0, item.Span.LineIndex); - Assert.Equal(@"The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. Use '@using ' directive instead.", item.GetMessage()); + Assert.Equal(@"The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. Use '@using ' directive instead.", item.GetMessage(CultureInfo.CurrentCulture)); }, item => { Assert.Equal("RZ9978", item.Id); Assert.Equal(1, item.Span.LineIndex); - Assert.Equal(@"The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. Use '@using ' directive instead.", item.GetMessage()); + Assert.Equal(@"The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. Use '@using ' directive instead.", item.GetMessage(CultureInfo.CurrentCulture)); }, item => { Assert.Equal("RZ9978", item.Id); Assert.Equal(2, item.Span.LineIndex); - Assert.Equal(@"The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. Use '@using ' directive instead.", item.GetMessage()); + Assert.Equal(@"The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. Use '@using ' directive instead.", item.GetMessage(CultureInfo.CurrentCulture)); }); } @@ -116,7 +117,7 @@ public class Test item => { Assert.Equal("RZ10003", item.Id); - Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage()); + Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage(CultureInfo.CurrentCulture)); }); } @@ -134,7 +135,7 @@ @section Foo { item => { Assert.Equal("RZ10003", item.Id); - Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage()); + Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage(CultureInfo.CurrentCulture)); }); } @@ -151,7 +152,7 @@ public void ErrorsForMarkup() item => { Assert.Equal("RZ10003", item.Id); - Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage()); + Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage(CultureInfo.CurrentCulture)); }); } @@ -172,19 +173,19 @@ public void ErrorsForCode() { Assert.Equal("RZ10003", item.Id); Assert.Equal(0, item.Span.LineIndex); - Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage()); + Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage(CultureInfo.CurrentCulture)); }, item => { Assert.Equal("RZ10003", item.Id); Assert.Equal(1, item.Span.LineIndex); - Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage()); + Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage(CultureInfo.CurrentCulture)); }, item => { Assert.Equal("RZ10003", item.Id); Assert.Equal(2, item.Span.LineIndex); - Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage()); + Assert.Equal(@"Markup, code and block directives are not valid in component imports.", item.GetMessage(CultureInfo.CurrentCulture)); }); } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpSectionTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpSectionTest.cs index 517dd4a83da1..7443891249cc 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpSectionTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/CSharpSectionTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Globalization; using Microsoft.AspNetCore.Razor.Language.Extensions; using Xunit; @@ -146,6 +147,7 @@ public void HandlesUnterminatedSectionWithNestedIf() // Act & Assert ParseDocumentTest( string.Format( + CultureInfo.InvariantCulture, "@section Test{0}{{{0}{1}@if(true){0}{1}{{{0}{1}{1}

Hello World

{0}{1}}}", newLine, spaces), diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperBlockRewriterTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperBlockRewriterTest.cs index b574dbdf1286..9d8d7c6ea2e5 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperBlockRewriterTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperBlockRewriterTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using Microsoft.AspNetCore.Razor.Language.Components; using Xunit; @@ -274,7 +275,7 @@ public void AllowsCompatibleTagStructures_DirectiveAttribute_Void() b.Name = "@onclick"; b.Metadata.Add(ComponentMetadata.Common.DirectiveAttribute, bool.TrueString); }); - + }) .AddMetadata(ComponentMetadata.SpecialKindKey, ComponentMetadata.EventHandler.TagHelperKind) .Build(), @@ -600,7 +601,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlock // Arrange var dateTimeNowString = "@DateTime.Now"; var currentFormattedString = "

"; - var document = string.Format(currentFormattedString, dateTimeNowString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, dateTimeNowString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -612,7 +613,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlock // Arrange var doWhileString = "@do { var foo = bar; Foo foo++; } while (foo);"; var currentFormattedString = "

"; - var document = string.Format(currentFormattedString, doWhileString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, doWhileString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -624,7 +625,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlock // Arrange var dateTimeNowString = "@DateTime.Now"; var currentFormattedString = "

Hello World

"; - var document = string.Format(currentFormattedString, dateTimeNowString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, dateTimeNowString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -636,7 +637,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlock // Arrange var doWhileString = "@do { var foo = bar; Foo foo++; } while (foo);"; var currentFormattedString = "

Hello World

"; - var document = string.Format(currentFormattedString, doWhileString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, doWhileString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -648,7 +649,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlock // Arrange var dateTimeNowString = "@DateTime.Now"; var currentFormattedString = "

Hello

World

"; - var document = string.Format(currentFormattedString, dateTimeNowString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, dateTimeNowString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -660,7 +661,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlock // Arrange var doWhileString = "@do { var foo = bar; Foo foo++; } while (foo);"; var currentFormattedString = "

Hello

World

"; - var document = string.Format(currentFormattedString, doWhileString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, doWhileString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -672,7 +673,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexAttributeTagHelperTagBlock // Arrange var dateTimeNowString = "@DateTime.Now"; var currentFormattedString = "

Hello World inside of strong tag

"; - var document = string.Format(currentFormattedString, dateTimeNowString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, dateTimeNowString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -684,7 +685,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks1() // Arrange var dateTimeNowString = "@DateTime.Now"; var currentFormattedString = "

{0}

"; - var document = string.Format(currentFormattedString, dateTimeNowString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, dateTimeNowString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -696,7 +697,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks2() // Arrange var doWhileString = "@do { var foo = bar;

Foo

foo++; } while (foo);"; var currentFormattedString = "

{0}

"; - var document = string.Format(currentFormattedString, doWhileString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, doWhileString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -708,7 +709,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks3() // Arrange var dateTimeNowString = "@DateTime.Now"; var currentFormattedString = "

Hello World {0}

"; - var document = string.Format(currentFormattedString, dateTimeNowString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, dateTimeNowString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -720,7 +721,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks4() // Arrange var doWhileString = "@do { var foo = bar;

Foo

foo++; } while (foo);"; var currentFormattedString = "

Hello World {0}

"; - var document = string.Format(currentFormattedString, doWhileString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, doWhileString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -732,7 +733,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks5() // Arrange var dateTimeNowString = "@DateTime.Now"; var currentFormattedString = "

{0}

{0}

"; - var document = string.Format(currentFormattedString, dateTimeNowString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, dateTimeNowString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -744,7 +745,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks6() // Arrange var doWhileString = "@do { var foo = bar;

Foo

foo++; } while (foo);"; var currentFormattedString = "

{0}

{0}

"; - var document = string.Format(currentFormattedString, doWhileString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, doWhileString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -756,7 +757,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks7() // Arrange var dateTimeNowString = "@DateTime.Now"; var currentFormattedString = "

Hello {0}inside of {0} strong tag

"; - var document = string.Format(currentFormattedString, dateTimeNowString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, dateTimeNowString); // Act & Assert RunParseTreeRewriterTest(document, "p"); @@ -768,7 +769,7 @@ public void TagHelperParseTreeRewriter_RewritesComplexTagHelperTagBlocks8() // Arrange var doWhileString = "@do { var foo = bar;

Foo

foo++; } while (foo);"; var currentFormattedString = "

Hello {0}inside of {0} strong tag

"; - var document = string.Format(currentFormattedString, doWhileString); + var document = string.Format(CultureInfo.InvariantCulture, currentFormattedString, doWhileString); // Act & Assert RunParseTreeRewriterTest(document, "p"); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperParseTreeRewriterTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperParseTreeRewriterTest.cs index 044f59124d48..bc7dcb362056 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperParseTreeRewriterTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TagHelperParseTreeRewriterTest.cs @@ -1271,6 +1271,13 @@ public void RequiredAttributeDescriptorsCreateMalformedTagHelperBlocksCorrectly1 EvaluateData(MalformedRequiredAttribute_Descriptors, "

"); } } -} \ No newline at end of file +} diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TokenizerTestBase.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TokenizerTestBase.cs index 21ccddba3b81..2c6d54daeeb2 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TokenizerTestBase.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/Legacy/TokenizerTestBase.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Globalization; using System.Text; using Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax; using Xunit; @@ -28,23 +29,23 @@ internal void TestTokenizer(string input, params SyntaxToken[] expectedSymbols) { if (counter >= expectedSymbols.Length) { - output.AppendLine(string.Format("F: Expected: << Nothing >>; Actual: {0}", current)); + output.AppendLine(string.Format(CultureInfo.InvariantCulture, "F: Expected: << Nothing >>; Actual: {0}", current)); success = false; } else if (ReferenceEquals(expectedSymbols[counter], IgnoreRemaining)) { - output.AppendLine(string.Format("P: Ignored |{0}|", current)); + output.AppendLine(string.Format(CultureInfo.InvariantCulture, "P: Ignored |{0}|", current)); } else { if (!expectedSymbols[counter].IsEquivalentTo(current)) { - output.AppendLine(string.Format("F: Expected: {0}; Actual: {1}", expectedSymbols[counter], current)); + output.AppendLine(string.Format(CultureInfo.InvariantCulture, "F: Expected: {0}; Actual: {1}", expectedSymbols[counter], current)); success = false; } else { - output.AppendLine(string.Format("P: Expected: {0}", expectedSymbols[counter])); + output.AppendLine(string.Format(CultureInfo.InvariantCulture, "P: Expected: {0}", expectedSymbols[counter])); } counter++; } @@ -54,7 +55,7 @@ internal void TestTokenizer(string input, params SyntaxToken[] expectedSymbols) success = false; for (; counter < expectedSymbols.Length; counter++) { - output.AppendLine(string.Format("F: Expected: {0}; Actual: << None >>", expectedSymbols[counter])); + output.AppendLine(string.Format(CultureInfo.InvariantCulture, "F: Expected: {0}; Actual: << None >>", expectedSymbols[counter])); } } } @@ -65,7 +66,7 @@ internal void TestTokenizer(string input, params SyntaxToken[] expectedSymbols) [Conditional("PARSER_TRACE")] private static void WriteTraceLine(string format, params object[] args) { - Trace.WriteLine(string.Format(format, args)); + Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, format, args)); } } } diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorLanguageVersionTest.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorLanguageVersionTest.cs index 6122de3eb4ca..4542300aac43 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorLanguageVersionTest.cs +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/RazorLanguageVersionTest.cs @@ -1,6 +1,7 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Linq; using System.Reflection; using Xunit; @@ -140,7 +141,7 @@ public void LatestPointsToNewestVersion() // Arrange var v = RazorLanguageVersion.Parse("latest"); var versions = typeof(RazorLanguageVersion).GetFields(BindingFlags.Public | BindingFlags.Static) - .Where(f => f.Name.StartsWith("Version_")) + .Where(f => f.Name.StartsWith("Version_", StringComparison.Ordinal)) .Select(f => f.GetValue(obj: null)) .Cast(); diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AddTagHelperDirective_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AddTagHelperDirective_DesignTime.codegen.html index 0da46f2152d1..9798fda642fa 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AddTagHelperDirective_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AddTagHelperDirective_DesignTime.codegen.html @@ -1 +1 @@ - +~~~~~~~~~~~~~ ~~~ ~~~~~~~~~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AttributeDirective_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AttributeDirective_DesignTime.codegen.html index fd82d1980659..bc07a83107e3 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AttributeDirective_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/AttributeDirective_DesignTime.codegen.html @@ -1,6 +1,6 @@ - - - - +~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~ +~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ Hello World \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Await_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Await_DesignTime.codegen.html index 22593ca1ef47..9206eae15e5b 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Await_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Await_DesignTime.codegen.html @@ -1,26 +1,26 @@ - - - - - - +~~~~~~~~~~ ~ + ~~~~~~ ~~~~~ ~~~~~~~~~~~~ ~~~~~ + ~ + ~~~~~~ ~~~~~~ + ~ +~

Basic Asynchronous Expression Test

-

Basic Asynchronous Expression:

-

Basic Asynchronous Template:

-

Basic Asynchronous Statement:

-

Basic Asynchronous Statement Nested:

-

Basic Incomplete Asynchronous Statement:

+

Basic Asynchronous Expression: ~~~~~~ ~~~~~

+

Basic Asynchronous Template: ~~~~~~~ ~~~~~~

+

Basic Asynchronous Statement: ~~ ~~~~~ ~~~~~~ ~

+

Basic Asynchronous Statement Nested: ~~ ~~~~~~ ~~~~~ ~

+

Basic Incomplete Asynchronous Statement: ~~~~~~

Advanced Asynchronous Expression Test

-

Advanced Asynchronous Expression:

-

Advanced Asynchronous Expression Extended:

-

Advanced Asynchronous Template:

-

Advanced Asynchronous Statement:

-

Advanced Asynchronous Statement Extended:

-

Advanced Asynchronous Statement Nested:

-

Advanced Incomplete Asynchronous Statement:

+

Advanced Asynchronous Expression: ~~~~~~ ~~~~~~ ~~

+

Advanced Asynchronous Expression Extended: ~~~~~~ ~~~~~~~~~~ ~~

+

Advanced Asynchronous Template: ~~~~~~~ ~~~~~~~~~~ ~~~~~~

+

Advanced Asynchronous Statement: ~~ ~~~~~ ~~~~~~~~~~~~~~ ~~~~~~ ~~~~~~~~~ ~

+

Advanced Asynchronous Statement Extended: ~~ ~~~~~ ~~~~~~~~~~ ~~ ~

+

Advanced Asynchronous Statement Nested: ~~ ~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~ ~

+

Advanced Incomplete Asynchronous Statement: ~~~~~~ ~~~~~~~~~~~~~

\ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Blocks_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Blocks_DesignTime.codegen.html index dc08c79219d9..b36df6862afd 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Blocks_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Blocks_DesignTime.codegen.html @@ -1,37 +1,37 @@ - - - +~~ + ~~~ ~ ~ ~~ +~ - -

Hello from C#, #

- - +~~~~~~~~ ~~ ~~~ ~ +

Hello from C#, #~~~~

+ ~ ~~ ~~ +~ - +~~~~~ ~~ ~~~ ~

We wrote 10 lines!

- +~ - - +~~~~~~~~~~ ~ + ~~~~ ~~~

No really, we wrote 10 lines!

- - + ~~~~~~ + ~~~~~~~~

Actually, we didn't...

- - + ~~~~~~ +~ - -

Hello again from C#, #

- +~~~~~~~~ ~ ~ ~~ ~ ~~ ~~~ ~ ~~ ~~ ~ +

Hello again from C#, #~~~~

+~ - +~~~~ ~

That time, we wrote 5 lines!

- -

Oh no! An error occurred:

- +~ ~~~~~~~~~~~~~~~ ~~~ ~ +

Oh no! An error occurred: ~~~~~~~~~~~~~

+~ -

i is now

+

i is now ~~

- +~~~~~~~~~ ~~~~~~~~~ ~

This block is locked, for your security!

- \ No newline at end of file +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp7_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp7_DesignTime.codegen.html index a2aad32abe93..d3e8f46d6bae 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp7_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp7_DesignTime.codegen.html @@ -1,43 +1,43 @@ - - - - - + ~~ + ~~~ ~~~~~~~~~~ ~ ~~~ ~~~~~~~~~~~~~~~~~~ ~~~~~~~ ~~~~~~~~~~ ~~~~~~ ~~~~~~~~~ ~~~~~~ ~~~~~~~~~ + ~ + ~~~~~~ ~~~~~ ~ ~~~~~~~~ ~~~~~~ ~~~~~ + ~~ - + ~~ ~~~~ ~~ ~~~ ~~ ~ ~~~~ ~~~~ ~~~~~~ ~~~~~ ~~ - - - - - + ~~~ ~~~~~~~ ~ ~~~~~~~~~~~~ + ~~~~ ~~~~~~~~~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~ + ~~~~~~ ~~~~~~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~ ~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ - - - - - - - + ~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~ ~~~ ~~~ ~~~~~~~ + ~ + ~~ ~~~~~~~~~~~~ ~~ ~~~~ ~~~~~~ + ~ + ~~ ~~ ~~~~~~~~~ + ~ + ~

- Here's a very unique number: + Here's a very unique number: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- + ~~~~~~~~~ ~~~~~~~ ~~~~~ ~~~~~~~~~~~~~ ~~ ~~~~~ ~~~~~~ ~~
- - - - - - - - - - - - + ~~~~~~~ ~~~~~~~~~~~~~ + ~ + ~~~~ ~~~ ~~~~ + ~~ ~~ ~~~~~~~~~ + ~~~~~~ + ~~~~ ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ + ~~ ~~ ~~~~ ~~~~~~~~~ + ~~~~~~ + ~~~~ ~~~~~ + ~~ ~~ ~~~~ ~~~~ ~~ ~~~~~~~~~ + ~~~~~~ + ~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.codegen.html index 2e0ee4dc6ebb..25245b195da1 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CSharp8_DesignTime.codegen.html @@ -1,67 +1,67 @@ - +~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - - +~~ + ~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ + ~ + ~~~~~~ ~~~~~ + ~ - - + ~~~~~ ~~~~~~~ ~~~~ ~~~ ~~ ~~~~~~~~~~~~~~~~~~~~~ + ~ - + ~ - - + ~~~~~ ~~~~~ ~ ~~~~~ + ~~~~~ ~~~ ~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - - - - - + ~~~ ~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~ + ~~~ ~~~~~~~~ ~ ~~~~~~~~~~ + ~~~~~~ ~~~~~~~~ ~~~~~~~~~ + ~ + ~~~~~~ ~~~~~~~~~~~~~~~ + ~ +~ - - +~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ - - - - - - +~~~~~~~~~~ ~~~~~~ +~ + ~~~~~~~~~~~~~~ ~~ ~~~~ ~~~~~~~~ + ~~~~~~~~~~~~~~~ ~~ ~~~~ ~~~~~~~~~ + ~ ~~ ~~~~ ~~~~~~~~ +~~ - - - - +~~~~~~ ~~~~~~~ ~~~~ ~~~ ~~ ~~~~~~~~~~~~~~~~~~~~~ +~ + ~~~~ +~ - - - +~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~ - - - - - - +~~~~~~~~~~ ~ + ~~~~ ~~~~~~~~ + ~ + ~~~~~~ + ~~~~~~ + ~ - - - - - + ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~ + ~ + ~~~ ~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~ + ~ - + ~~~~~~~ ~~~~~~ ~~~~~~ ~ ~~~~ ~~~~ ~ - + ~~~~~~~ ~~~~~~~~~ ~~~~~~ ~ ~~~~ ~~~~ ~ - + ~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~ ~~~~~~~~~~~ ~ ~~~~ ~~~~ ~ - - - - - \ No newline at end of file + ~~~~~~~ ~~~~~ ~~~~~ + ~ + ~~~~~~ ~~~~~~~ ~~~~ ~ ~~~~ ~~~~ ~ + ~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlockAtEOF_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlockAtEOF_DesignTime.codegen.html index 136d06384a4c..68db24f6303b 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlockAtEOF_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlockAtEOF_DesignTime.codegen.html @@ -1 +1 @@ - \ No newline at end of file +~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlockWithTextElement_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlockWithTextElement_DesignTime.codegen.html index a6e01f1a0e64..738f635fb736 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlockWithTextElement_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlockWithTextElement_DesignTime.codegen.html @@ -1,4 +1,4 @@ - - foo - bar - +~~ + ~~~ ~ ~ ~~ foo + ~~~ ~ ~ ~~ bar ~~~~~~ +~ diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlock_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlock_DesignTime.codegen.html index f857199dcf16..9a924676bc4d 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlock_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/CodeBlock_DesignTime.codegen.html @@ -1,5 +1,5 @@ - - - - - \ No newline at end of file +~~ + ~~~~~~~ ~ ~ ~~ ~ ~~ ~~~ ~~~~ ~ + ~~~~~~~~~~~~~~~~~~~~~~ ~~~~ ~~~ ~~ ~ ~~~~~~~~~~~~ ~ ~~~~~~~~ + ~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.html index 46a4402680ba..6d16f3df2c5f 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ConditionalAttributes_DesignTime.codegen.html @@ -1,15 +1,15 @@ - - - +~~ + ~~~ ~~ ~ ~~~~~ + ~~~ ~~~ ~ ~~~~~~ -

-

-

- - -

+

+

+

+ + +

- - + + - \ No newline at end of file +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DesignTime_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DesignTime_DesignTime.codegen.html index be5ba4979a03..a8754ea813a0 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DesignTime_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/DesignTime_DesignTime.codegen.html @@ -1,15 +1,15 @@

- -

Bar Biz

+~~~~~~~~~~~~~~~ +~~~~~~

Bar ~~~~ Biz

~

- +~~~~~~~~ ~~~~~~ ~

Foo

- - \ No newline at end of file + ~~~~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyCodeBlock_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyCodeBlock_DesignTime.codegen.html index 9ebe0e3a7822..99a7f08ac047 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyCodeBlock_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyCodeBlock_DesignTime.codegen.html @@ -1,3 +1,3 @@ This is markup - \ No newline at end of file +~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyExplicitExpression_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyExplicitExpression_DesignTime.codegen.html index 9ebe0e3a7822..99a7f08ac047 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyExplicitExpression_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyExplicitExpression_DesignTime.codegen.html @@ -1,3 +1,3 @@ This is markup - \ No newline at end of file +~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyImplicitExpressionInCode_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyImplicitExpressionInCode_DesignTime.codegen.html index 1568f6aa34f3..0c15e1469835 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyImplicitExpressionInCode_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyImplicitExpressionInCode_DesignTime.codegen.html @@ -1,3 +1,3 @@ - - - \ No newline at end of file +~~ + ~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyImplicitExpression_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyImplicitExpression_DesignTime.codegen.html index 76ee36910b47..758fb714e81e 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyImplicitExpression_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/EmptyImplicitExpression_DesignTime.codegen.html @@ -1,3 +1,3 @@ This is markup - ! \ No newline at end of file +~! \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionAtEOF_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionAtEOF_DesignTime.codegen.html index 6eaf3f7aa0bd..d166c19f55a0 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionAtEOF_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionAtEOF_DesignTime.codegen.html @@ -1,3 +1,3 @@ This is markup - \ No newline at end of file +~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionWithMarkup_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionWithMarkup_DesignTime.codegen.html index fc593178498f..b410eec8a5e2 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionWithMarkup_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpressionWithMarkup_DesignTime.codegen.html @@ -1 +1 @@ -
\ No newline at end of file +
~~~
\ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpression_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpression_DesignTime.codegen.html index 33b749a2f937..152cef197aeb 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpression_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExplicitExpression_DesignTime.codegen.html @@ -1 +1 @@ -1 + 1 = \ No newline at end of file +1 + 1 = ~~~~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExpressionsInCode_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExpressionsInCode_DesignTime.codegen.html index de86958addfc..557c25099c9c 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExpressionsInCode_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ExpressionsInCode_DesignTime.codegen.html @@ -1,16 +1,16 @@ - - - - +~~ + ~~~~~~ ~~~ ~ ~~~~~ + ~~~~~~ ~~~ ~ ~~~~~~ +~ - - - +~~~~~~~ ~~ ~~~~~ ~ + ~~~~ +~ ~~~~ ~

Foo is Null!

- +~

- - - +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ + ~~~~~~~~~~~~~~~~~~ ~~~~~ +~

\ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/FunctionsBlockMinimal_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/FunctionsBlockMinimal_DesignTime.codegen.html index 6393f9703b5f..2a7f3ddff8a3 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/FunctionsBlockMinimal_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/FunctionsBlockMinimal_DesignTime.codegen.html @@ -1,7 +1,7 @@ - - - - - \ No newline at end of file + ~~~~~~~~~~~ +~~~~~~ ~~~~~~~~~~ ~~~~~~ ~ + ~~~~~~ ~~~~~ ~ ~~~~ +~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/FunctionsBlock_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/FunctionsBlock_DesignTime.codegen.html index 46d84b460b85..896d2c841527 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/FunctionsBlock_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/FunctionsBlock_DesignTime.codegen.html @@ -1,12 +1,12 @@ - +~~~~~~~~~~ ~ - +~ - - - - - - +~~~~~~~~~~ ~ + ~~~~~~ ~~~~~ ~ ~~~ ~~~~~~~~~ + ~~~~~~~ ~~~ ~~~~~~~~~~~ ~ + ~~~~~~ ~~~~~~~~~~~~~ + ~ +~ -Here's a random number: \ No newline at end of file +Here's a random number: ~~~~~~~~~~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/HiddenSpansInCode_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/HiddenSpansInCode_DesignTime.codegen.html index 13484a1b456c..88647e0895ab 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/HiddenSpansInCode_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/HiddenSpansInCode_DesignTime.codegen.html @@ -1,3 +1,3 @@ - - - \ No newline at end of file +~~ + ~~~~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Implements_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Implements_DesignTime.codegen.html index d0776340e1a6..8d87a8e68a75 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Implements_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Implements_DesignTime.codegen.html @@ -1,5 +1,5 @@ - +~~~~~~~~~~~ ~~~~~~~~~~~ - - - \ No newline at end of file +~~~~~~~~~~ ~ + ~~~~ ~~~~~~~~~~~~~~~~~~~~~ ~ ~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ImplicitExpressionAtEOF_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ImplicitExpressionAtEOF_DesignTime.codegen.html index f1c2edafa225..28138a2cddf2 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ImplicitExpressionAtEOF_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ImplicitExpressionAtEOF_DesignTime.codegen.html @@ -1,3 +1,3 @@ This is markup - \ No newline at end of file +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ImplicitExpression_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ImplicitExpression_DesignTime.codegen.html index c3ca733a2bc7..b8f7cde9f741 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ImplicitExpression_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ImplicitExpression_DesignTime.codegen.html @@ -1,3 +1,3 @@ - -

This is item #

- \ No newline at end of file +~~~~~~~~ ~ ~ ~~ ~ ~~ ~~~ ~~~~ ~ +

This is item #~~

+~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.html index b7d08f385618..d932435cea17 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives_DesignTime.codegen.html @@ -1,25 +1,25 @@ - +~~ ~~~~~ ~~~~ ~~~~~ ~~~~~~~~ ~~~~ ~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~ ~~~~~~ ~~ - - - +~~~~~~~~~~~~~ +~~~~~~~~~~~~~ +~~~~~~~~~~~~~ ~ - - - +~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ ~ - - - +~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~ ~ - - +~~~~~~~~~ +~~~~~~~~~ - - +~~~~~~~~~~ +~~~~~~~~~~ - - +~~~~~~~~ +~~~~~~~~ - { - \ No newline at end of file +~~~~~~~~ { +~~~~~~~~~~ ~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Inherits_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Inherits_DesignTime.codegen.html index b60ac0100e38..9cd1d59959a7 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Inherits_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Inherits_DesignTime.codegen.html @@ -1,3 +1,3 @@ - +~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ - \ No newline at end of file +~~~~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.codegen.html index 3b6fa1cd0620..18ebd6d308e5 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/InlineBlocks_DesignTime.codegen.html @@ -1,3 +1,3 @@ - (string link) { -
+~~~~~~~~ ~~~~(string link) { + } \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Instrumented_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Instrumented_DesignTime.codegen.html index 111d1f7474ce..1c44204c9352 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Instrumented_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Instrumented_DesignTime.codegen.html @@ -1,38 +1,38 @@ - - -

Bar

- Hello, World +~~ + ~~~ ~ ~ ~~ + ~~~ ~~~ ~ ~

Bar

~ + ~~Hello, World

Hello, World

- +~ - -

Hello from C#, #

- - +~~~~~~~~ ~~ ~~~ ~ +

Hello from C#, #~~~~

+ ~ ~~ ~~ +~ - +~~~~~ ~~ ~~~ ~

We wrote 10 lines!

- +~ - - +~~~~~~~~~~ ~ + ~~~~ ~~~

No really, we wrote 10 lines!

- - + ~~~~~~ + ~~~~~~~~

Actually, we didn't...

- - + ~~~~~~ +~ - -

Hello again from C#, #

- +~~~~~~~~ ~ ~ ~~ ~ ~~ ~~~ ~ ~~ ~~ ~ +

Hello again from C#, #~~~~

+~ - +~~~~ ~

That time, we wrote 5 lines!

- -

Oh no! An error occurred:

- +~ ~~~~~~~~~~~~~~~ ~~~ ~ +

Oh no! An error occurred: ~~~~~~~~~~~~~

+~ - +~~~~~~~~~ ~~~~~~~~~ ~

This block is locked, for your security!

- \ No newline at end of file +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MarkupInCodeBlock_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MarkupInCodeBlock_DesignTime.codegen.html index 9148ce732370..ad3e1315f2bd 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MarkupInCodeBlock_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MarkupInCodeBlock_DesignTime.codegen.html @@ -1,5 +1,5 @@ - - -

Hello from C#, #

- - +~~ + ~~~~~~~ ~ ~ ~~ ~ ~~ ~~~ ~~~~ ~ +

Hello from C#, #~~~~~~~~~~~~~~~

+ ~ +~ diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Markup_InCodeBlocks_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Markup_InCodeBlocks_DesignTime.codegen.html index 4b346c914a4b..554040f8c49a 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Markup_InCodeBlocks_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Markup_InCodeBlocks_DesignTime.codegen.html @@ -1,45 +1,45 @@ - - - - - - - - -
- - - - - - - - - - +~~ + ~~~ ~~~~~~ ~ ~~~ ~~~~~~~~ + ~ + ~~~ ~~~~~~~~ ~ ~~~~ ~ ~~~~~~~~~ ~~~ ~ ~~~ ~ + ~~ + + ~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~ + ~ +
~~~~~~~~~~~~
+ ~ +~ + +~~ ~~~~~~~~~~~~~~~~~~~~ ~ +~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ + +~~~~~~~~~~ ~ + ~~~~ ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~ + ~ + ~~~ ~~~~~~~~~ ~ ~~~~~ ~~~~~~~~~~~~~~~
-

Happy birthday !

+

Happy birthday ~~~~~~~~~~~~!

    - - -
  • Happy birthday!
  • - + ~~~~ ~~~~ ~ ~ ~~ ~ ~ ~~~~~~~~~~ ~ ~~~ ~~~~ + ~ +
  • ~~~~ Happy birthday!
  • + ~
- - - - + ~~ ~~~~~~~~~~~ ~ ~~~ + ~ + ~~~~~~~ + ~

Secret message

- - - - - - - - \ No newline at end of file + ~ + + ~~~~~ ~~~~~~ + ~ + ~~~~~~ ~~~~~~ ~~~~ ~ ~~~~ ~~~~ ~ + ~~~~~~ ~~~ ~~~ ~ ~~~~ ~~~~ ~ + ~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NestedCSharp_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NestedCSharp_DesignTime.codegen.html index c1b9240ee07a..1a78d3888c91 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NestedCSharp_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NestedCSharp_DesignTime.codegen.html @@ -1,8 +1,8 @@ - - - +~~ + ~~~~~~~~ ~~~~ ~~~~~~ ~~ ~~~~~~~~~~~~~ + ~
- . + ~~~~~~~~~~~~~~~~~.
- - \ No newline at end of file + ~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NestedCodeBlocks_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NestedCodeBlocks_DesignTime.codegen.html index c56380dfcb99..966b588e290f 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NestedCodeBlocks_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NestedCodeBlocks_DesignTime.codegen.html @@ -1,4 +1,4 @@ - - - - \ No newline at end of file +~~~~~~~~ ~ + ~~~~~~~~ ~ + ~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NoLinePragmas_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NoLinePragmas_DesignTime.codegen.html index b7c02278c1d0..494393779b10 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NoLinePragmas_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NoLinePragmas_DesignTime.codegen.html @@ -1,38 +1,38 @@ - - - +~~ + ~~~ ~ ~ ~~ +~ - -

Hello from C#, #

- - +~~~~~~~~ ~~ ~~~ ~ +

Hello from C#, #~~~~

+ ~ ~~ ~~ +~ - +~~~~~ ~~ ~~~ ~

We wrote 10 lines!

- +~ - - +~~~~~~~~~~ ~ + ~~~~ ~~~

No really, we wrote 10 lines!

- - + ~~~~~~ + ~~~~~~~~

Actually, we didn't...

- - + ~~~~~~ +~ - -

Hello again from C#, #

- +~~~~~~~~ ~ ~ ~~ ~ ~~ ~~~ ~ ~~ ~~ ~ +

Hello again from C#, #~~~~

+~ - +~~~~ ~

That time, we wrote 5 lines!

- -

Oh no! An error occurred:

- +~ ~~~~~~~~~~~~~~~ ~~~ ~ +

Oh no! An error occurred: ~~~~~~~~~~~~~

+~ - -

i is now

+~~ ~~~~ ~~~ ~~ ~~~~~~~~~~ ~~ ~~ ~~ +

i is now ~~

- +~~~~~~~~~ ~~~~~~~~~ ~

This block is locked, for your security!

- \ No newline at end of file +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NullConditionalExpressions_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NullConditionalExpressions_DesignTime.codegen.html index 7ad423b1f29e..e40e3c6f4954 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NullConditionalExpressions_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/NullConditionalExpressions_DesignTime.codegen.html @@ -1,11 +1,11 @@ - - - - - - +~~ + ~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~ - - - - \ No newline at end of file +~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/OpenedIf_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/OpenedIf_DesignTime.codegen.html index 1675f6438378..42ba9c64b06a 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/OpenedIf_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/OpenedIf_DesignTime.codegen.html @@ -1,5 +1,5 @@ - +~~~ ~~~~~~ ~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ParserError_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ParserError_DesignTime.codegen.html index d0076463280f..61e3b424cb11 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ParserError_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/ParserError_DesignTime.codegen.html @@ -1,5 +1,5 @@ - - - - - \ No newline at end of file +~~ +~~ +~~~ ~ ~~~~ +~~~ ~ ~~~~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_DesignTime.codegen.html index f851e2e59774..d4faa3491649 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments_DesignTime.codegen.html @@ -1,18 +1,18 @@ - -

This should be shown

+~~~~~~ ~~ ~~~ ~~~~~ ~~ ~~ ~~~~~~~~~~ +

This should ~~ ~~~ ~~ be shown

- - - - - - - +~~ + ~~ ~~~~~ ~~~ ~~~~~~~~~~~~~ ~~~~~ ~~ + ~~~~~~~~~ ~~~ ~ ~~ ~~~ ~~~~~~~~~~~~~ ~~~~~ ~~ ~~~~~ + ~~~~~~ ~~ ~~~~~ ~ + ~~~~~ ~~~~ + ~ +~ - -

But this should show the comment syntax:

+~~ ~~~ ~~~ ~ ~~~ ~~~ ~~~~ ~ +

But this should show the comment syntax: ~~~~

- +~~~~~~~~~ - + diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RemoveTagHelperDirective_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RemoveTagHelperDirective_DesignTime.codegen.html index 77def406f5ff..1460ade1eacc 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RemoveTagHelperDirective_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RemoveTagHelperDirective_DesignTime.codegen.html @@ -1 +1 @@ - +~~~~~~~~~~~~~~~~ ~~ ~~~~~~~~~~~~ diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections_DesignTime.codegen.html index 72ff37f26cb5..b47779a0df74 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Sections_DesignTime.codegen.html @@ -1,17 +1,17 @@ - - - +~~ + ~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~
This is in the Body> - -
This is in Section 2
- +~~~~~~~~ ~~~~~~~~ ~ +
This is in Section 2
+~ - +~~~~~~~~ ~~~~~~~~ ~
This is in Section 1
- +~ - - - \ No newline at end of file +~~~~~~~~ ~~~~~~~~~~~~~~~ ~ + ~~ ~~~~~~~~~~~~~ ~~~~~~~ ~ ~ ~~~~~~~ ~ +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/SimpleUnspacedIf_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/SimpleUnspacedIf_DesignTime.codegen.html index 11a63ced54cf..221eda5a6c0f 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/SimpleUnspacedIf_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/SimpleUnspacedIf_DesignTime.codegen.html @@ -1,4 +1,4 @@ - - +~~~ ~~~~~~ +~
- \ No newline at end of file +~ \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/SingleLineControlFlowStatements_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/SingleLineControlFlowStatements_DesignTime.codegen.html index 3d06dc8b909c..897f7e85741e 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/SingleLineControlFlowStatements_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/SingleLineControlFlowStatements_DesignTime.codegen.html @@ -1,102 +1,102 @@

Before Text

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +~~ + ~~ ~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~ ~~ ~~ ~~~~~~~~~~ ~~~~ ~~ ~~~~~~~~~ ~~ ~~~ ~~~~ ~~~~~~~~~~~~~ + + ~~~~~~ ~~~~~ + ~ + ~~ ~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~ ~~ ~~ + ~~~~~~ ~~~~~~~~ ~~~~ ~~ ~~~~~~~~~ ~~ ~~~ + ~~~~ ~~ ~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~ ~~ ~~ + ~~~~~~ ~~~~~~~~ ~~~~ ~~ ~~~~~~~~~ ~~ ~~~ + ~~~~ + ~~~~~~ ~~~~~~~~~~~~~ + ~ + + ~~~ ~~~~ ~ ~ ~~ ~ ~ ~~~ ~~~~ + ~~ ~~~~~~~~~~~~ ~ ~~~~~~ + ~~~~ + + ~~~~~~~~ ~~~~ ~~~~ ~~ ~~~~~ ~~~~~~~~~~ + ~~~~~ + + ~~ + ~~~~~~~~~~~~~ + ~~~~~ ~~~~~~~~~~~~~~~ ~~ ~~~ + + ~~~~~ ~~~~~~~~~~~~~~~ ~~ ~~~ + ~~~~~~~~~~~~~~~ + + ~~~~~ ~~~~ ~~~~~~ ~ ~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~ + + ~~~~~ ~~~~~~ + ~~~~~~~~~~~~~~~ +~ + +~~~~~~~~~~ ~ + ~~~~~~ ~~~~~~ ~~~~~ + ~ + ~~~ ~ ~ ~~~ + + ~~ ~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~ ~~ ~~ + ~~~~~~ ~~~~~~~~ ~~~~ ~~ ~~~~~~~~~ ~~ ~~~ + ~~~~ + ~~~~~~ ~~~ ~~~~~ ~~~~~~~~~ ~~ ~~~~~ - - - + ~~~ ~~~~ ~ ~ ~~ ~ ~ ~~~ ~~~~ + ~~ ~~~~~~~~~~~~ ~ ~~~~~~ + ~~~~ - - + ~~~~~~~ ~~~~ ~~~~ ~~ ~~~~~ ~~~~~~~~~~ + ~~~~~ - - - + ~~ + ~~~~~~~~~~~~~ + ~~~~~ ~~~~~~~~~~~~~~~ ~~ ~~~ - - + ~~~~~ ~~~~~~~~~~~~~~~ ~~ ~~~ + ~~~~~~~~~~~~~~~ - - + ~~~~~ ~~~~ ~~~~~~ ~ ~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~~~~~~~~~~~~~~~ - - - + ~~~~ ~~~~~~ + ~~~~~~~~~~~~~~~ + ~ - + ~~~ ~~~~~~~~~~~~ ~ ~~ - - - - + ~~~~~~ ~~~~ ~~~~~~~~~~~~~~~~ + ~ + ~~ ~~~~~~ ~~~~~~~~~~~~~~~ + ~ - +~ - - +~~~~ ~~~~ ~ ~ ~~ ~ ~ ~~~ ~~~~ + ~~ - - +~~~~~~~~ ~~~~ ~~~~ ~~ ~~~~~ ~~~~~~~~~~ + ~~~~~ - - - +~~~ + ~~~~~~~~~~~~~ +~~~~~ ~~~~~~~~~~~~~~~ ~~ ~~~ - - +~~~~~~ ~~~~~~~~~~~~~~~ ~~ ~~~ + ~~~~~~~~~~~~~~~ - - - +~~~~~~ ~~~~ ~~~~~~ ~ ~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~ ~~~~~~~ ~~~ ~~~~~~ ~~~~ + ~~~~~~~~~~~~~~~~~~~ - - +~~~~~ ~~~~~~ + ~~~~~~~~~~~~~~~ -

Hello!

+~~~ ~~~~~~ ~~~~~~~~~~~~~~~~

Hello!

- -

The time is

+~~~ ~~~~~~ + ~~

The time is ~~~~~~~~~~~~~

After Text

\ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/StringLiterals_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/StringLiterals_DesignTime.codegen.html index b47c6a931ccb..823fe9a3eed3 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/StringLiterals_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/StringLiterals_DesignTime.codegen.html @@ -83,7 +83,7 @@

This is line 83

This is line 84


- +~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ ~

This is line 1 nested

This is line 2 nested

This is line 3 nested

@@ -159,7 +159,7 @@

This is line 73 nested

This is line 74 nested

This is line 75 nested

- +~

This is line 1

This is line 2

This is line 3

@@ -203,7 +203,7 @@

This is line 41

This is line 42

This is line 43

hi! - +~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~ ~

This is line 1 nested

This is line 2 nested

This is line 3 nested

@@ -234,4 +234,4 @@

This is line 28 nested

This is line 29 nested

30

- ! \ No newline at end of file +~! \ No newline at end of file diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Tags_DesignTime.codegen.html b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Tags_DesignTime.codegen.html index 419c13c11c9b..0dfbab3b0cdc 100644 --- a/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Tags_DesignTime.codegen.html +++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/test/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/Tags_DesignTime.codegen.html @@ -1,6 +1,6 @@ - - - +~~ + +~
{0}/
{0} {1}