diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index 00d95c3a1d..48f6535fbe 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -328,7 +328,7 @@ jobs: agentOs: Windows isTestingJob: true buildScript: ./eng/scripts/cibuild.cmd - buildArgs: -test -BuildNative "/p:SkipIISBackwardsCompatibilityTests=true /p:SkipIISTests=true /p:SkipIISExpressTests=true /p:SkipIISForwardsCompatibilityTests=true /p:RunTemplateTests=false /p:BuildSiteExtensions=false" + buildArgs: -test -BuildNative "/p:SkipIISNewHandlerTests=true /p:SkipIISTests=true /p:SkipIISExpressTests=true /p:SkipIISNewShimTests=true /p:RunTemplateTests=false /p:BuildSiteExtensions=false" beforeBuild: - powershell: "& ./src/Servers/IIS/tools/UpdateIISExpressCertificate.ps1; & ./src/Servers/IIS/tools/update_schema.ps1" displayName: Setup IISExpress test certificates and schema diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 4830722a42..7b7384d1c1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,384 +13,384 @@ https://github.com/aspnet/Blazor 9bc8036bf68fd159fffa56f93f8b2471bf96efd4 - + https://github.com/aspnet/AspNetCore-Tooling - 6fcd12e60b3d828988cabdebb55d30397c21d0db + 1954d93d9091707fef3958e63fc39b20325696df - + https://github.com/aspnet/AspNetCore-Tooling - 6fcd12e60b3d828988cabdebb55d30397c21d0db + 1954d93d9091707fef3958e63fc39b20325696df - + https://github.com/aspnet/AspNetCore-Tooling - 6fcd12e60b3d828988cabdebb55d30397c21d0db + 1954d93d9091707fef3958e63fc39b20325696df - + https://github.com/aspnet/AspNetCore-Tooling - 6fcd12e60b3d828988cabdebb55d30397c21d0db + 1954d93d9091707fef3958e63fc39b20325696df - + https://github.com/aspnet/EntityFrameworkCore - b9c9b57de1ba41f75427db0a51b2e897d0354656 + d09c10d233d284cd6406e04c31730c520c0e5cc5 - + https://github.com/aspnet/EntityFrameworkCore - b9c9b57de1ba41f75427db0a51b2e897d0354656 + d09c10d233d284cd6406e04c31730c520c0e5cc5 - + https://github.com/aspnet/EntityFrameworkCore - b9c9b57de1ba41f75427db0a51b2e897d0354656 + d09c10d233d284cd6406e04c31730c520c0e5cc5 - + https://github.com/aspnet/EntityFrameworkCore - b9c9b57de1ba41f75427db0a51b2e897d0354656 + d09c10d233d284cd6406e04c31730c520c0e5cc5 - + https://github.com/aspnet/EntityFrameworkCore - b9c9b57de1ba41f75427db0a51b2e897d0354656 + d09c10d233d284cd6406e04c31730c520c0e5cc5 - + https://github.com/aspnet/EntityFrameworkCore - b9c9b57de1ba41f75427db0a51b2e897d0354656 + d09c10d233d284cd6406e04c31730c520c0e5cc5 - + https://github.com/aspnet/EntityFrameworkCore - b9c9b57de1ba41f75427db0a51b2e897d0354656 + d09c10d233d284cd6406e04c31730c520c0e5cc5 - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a https://github.com/dotnet/corefx a28176b5ec68b6da1472934fe9493790d1665cae - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/dotnet/core-setup - fdf81c6faf7c7e0463d191a3a1d36c25c201e5cb + c113140681cdb8224dffc2da8df3e2f9bcbdc4a0 - + https://github.com/dotnet/core-setup - fdf81c6faf7c7e0463d191a3a1d36c25c201e5cb + c113140681cdb8224dffc2da8df3e2f9bcbdc4a0 - + https://github.com/dotnet/core-setup - fdf81c6faf7c7e0463d191a3a1d36c25c201e5cb + c113140681cdb8224dffc2da8df3e2f9bcbdc4a0 - + https://github.com/dotnet/corefx - d47cae744ddfb625db8e391cecb261e4c3d7bb1c + 55950a7c733de83f2efbafd3b5cad23e3ea6873a - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed https://github.com/dotnet/arcade @@ -404,9 +404,9 @@ https://github.com/dotnet/arcade e6a5d5f970bb872451c6310ae34eda31041fb552 - + https://github.com/aspnet/Extensions - 54d51a340698b6883dd3e47be372c07e0acf75bc + ef5d488c054c3aa850c29c10d851fcdc8a004eed diff --git a/eng/Versions.props b/eng/Versions.props index 248d132a8a..41cb537d43 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -23,108 +23,108 @@ 1.0.0-beta.19302.2 - 3.0.0-preview6-27804-01 - 3.0.0-preview6-27804-01 - 2.1.0-preview6-27804-01 + 3.0.0-preview7-27803-11 + 3.0.0-preview7-27803-11 + 2.1.0-preview7-27803-11 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 4.7.0-preview6.19264.9 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 1.7.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 - 4.6.0-preview6.19303.8 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 1.7.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 + 4.6.0-preview7.19303.5 - 3.0.0-preview6.19303.8 + 3.0.0-preview7.19303.5 0.10.0-preview7.19303.2 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 - 3.0.0-preview6.19304.6 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 + 3.0.0-preview7.19304.12 - 3.0.0-preview7.19303.12 - 3.0.0-preview7.19303.12 - 3.0.0-preview7.19303.12 - 3.0.0-preview7.19303.12 - 3.0.0-preview7.19303.12 - 3.0.0-preview7.19303.12 - 3.0.0-preview7.19303.12 + 3.0.0-preview7.19304.9 + 3.0.0-preview7.19304.9 + 3.0.0-preview7.19304.9 + 3.0.0-preview7.19304.9 + 3.0.0-preview7.19304.9 + 3.0.0-preview7.19304.9 + 3.0.0-preview7.19304.9 - 3.0.0-preview7.19303.10 - 3.0.0-preview7.19303.10 - 3.0.0-preview7.19303.10 - 3.0.0-preview7.19303.10 + 3.0.0-preview7.19304.5 + 3.0.0-preview7.19304.5 + 3.0.0-preview7.19304.5 + 3.0.0-preview7.19304.5 - - 14.16.27023 - diff --git a/eng/scripts/vs.buildtools.json b/eng/scripts/vs.buildtools.json index c487303d41..173ce44d40 100644 --- a/eng/scripts/vs.buildtools.json +++ b/eng/scripts/vs.buildtools.json @@ -17,8 +17,6 @@ "Microsoft.VisualStudio.Component.NuGet.BuildTools", "Microsoft.VisualStudio.Component.VC.ATL", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", - "Microsoft.VisualStudio.Component.VC.v141.ATL", - "Microsoft.VisualStudio.Component.VC.v141.x86.x64", "Microsoft.VisualStudio.Component.Windows10SDK.17134", "Microsoft.VisualStudio.Workload.ManagedDesktopBuildTools", "Microsoft.VisualStudio.Workload.MSBuildTools", diff --git a/eng/scripts/vs.json b/eng/scripts/vs.json index c0596cbf3c..d5aff9345a 100644 --- a/eng/scripts/vs.json +++ b/eng/scripts/vs.json @@ -15,8 +15,6 @@ "Microsoft.VisualStudio.Component.Azure.Storage.Emulator", "Microsoft.VisualStudio.Component.VC.ATL", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", - "Microsoft.VisualStudio.Component.VC.v141.ATL", - "Microsoft.VisualStudio.Component.VC.v141.x86.x64", "Microsoft.VisualStudio.Component.Windows10SDK.17134", "Microsoft.VisualStudio.Workload.ManagedDesktop", "Microsoft.VisualStudio.Workload.NativeDesktop", diff --git a/korebuild.json b/korebuild.json index 1618e0e746..e189d4b1de 100644 --- a/korebuild.json +++ b/korebuild.json @@ -16,8 +16,6 @@ "requiredWorkloads": [ "Microsoft.VisualStudio.Component.VC.ATL", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", - "Microsoft.VisualStudio.Component.VC.v141.ATL", - "Microsoft.VisualStudio.Component.VC.v141.x86.x64", "Microsoft.VisualStudio.Component.Windows10SDK.17134" ] } diff --git a/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.netcoreapp3.0.cs b/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.netcoreapp3.0.cs index 1b7b978add..cbeec0f51c 100644 --- a/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.netcoreapp3.0.cs +++ b/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.netcoreapp3.0.cs @@ -145,7 +145,6 @@ namespace Microsoft.AspNetCore.Hosting.Internal public static void Initialize(this Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment, string contentRootPath, Microsoft.AspNetCore.Hosting.Internal.WebHostOptions options) { } public static void Initialize(this Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnvironment, string contentRootPath, Microsoft.AspNetCore.Hosting.Internal.WebHostOptions options) { } } - [System.Diagnostics.Tracing.EventSourceAttribute(Name="Microsoft-AspNetCore-Hosting")] public sealed partial class HostingEventSource : System.Diagnostics.Tracing.EventSource { internal HostingEventSource() { } @@ -154,6 +153,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal public void HostStart() { } [System.Diagnostics.Tracing.EventAttribute(2, Level=System.Diagnostics.Tracing.EventLevel.Informational)] public void HostStop() { } + protected override void OnEventCommand(System.Diagnostics.Tracing.EventCommandEventArgs command) { } [System.Diagnostics.Tracing.EventAttribute(3, Level=System.Diagnostics.Tracing.EventLevel.Informational)] public void RequestStart(string method, string path) { } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Diagnostics.Tracing.EventAttribute(4, Level=System.Diagnostics.Tracing.EventLevel.Informational)] diff --git a/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs b/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs index 14aa549139..9428a56678 100644 --- a/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs +++ b/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs @@ -136,10 +136,19 @@ namespace Microsoft.AspNetCore.Hosting.Internal StopActivity(httpContext, activity, context.HasDiagnosticListener); } - if (context.EventLogEnabled && exception != null) + if (context.EventLogEnabled) { - // Non-inline - HostingEventSource.Log.UnhandledException(); + if (exception != null) + { + // Non-inline + HostingEventSource.Log.UnhandledException(); + } + + // Count 500 as failed requests + if (httpContext.Response.StatusCode >= 500) + { + HostingEventSource.Log.RequestFailed(); + } } // Logging Scope is finshed with diff --git a/src/Hosting/Hosting/src/Internal/HostingEventSource.cs b/src/Hosting/Hosting/src/Internal/HostingEventSource.cs index 199f8aae85..2b8d188373 100644 --- a/src/Hosting/Hosting/src/Internal/HostingEventSource.cs +++ b/src/Hosting/Hosting/src/Internal/HostingEventSource.cs @@ -1,17 +1,37 @@ -// 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.Tracing; using System.Runtime.CompilerServices; +using System.Threading; namespace Microsoft.AspNetCore.Hosting.Internal { - [EventSource(Name = "Microsoft-AspNetCore-Hosting")] public sealed class HostingEventSource : EventSource { public static readonly HostingEventSource Log = new HostingEventSource(); - private HostingEventSource() { } + private IncrementingPollingCounter _requestsPerSecondCounter; + private PollingCounter _totalRequestsCounter; + private PollingCounter _failedRequestsCounter; + private PollingCounter _currentRequestsCounter; + + private long _totalRequests; + private long _currentRequests; + private long _failedRequests; + + internal HostingEventSource() + : this("Microsoft.AspNetCore.Hosting") + { + + } + + // Used for testing + internal HostingEventSource(string eventSourceName) + : base(eventSourceName) + { + } // NOTE // - The 'Start' and 'Stop' suffixes on the following event names have special meaning in EventSource. They @@ -35,6 +55,8 @@ namespace Microsoft.AspNetCore.Hosting.Internal [Event(3, Level = EventLevel.Informational)] public void RequestStart(string method, string path) { + Interlocked.Increment(ref _totalRequests); + Interlocked.Increment(ref _currentRequests); WriteEvent(3, method, path); } @@ -42,6 +64,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal [Event(4, Level = EventLevel.Informational)] public void RequestStop() { + Interlocked.Decrement(ref _currentRequests); WriteEvent(4); } @@ -51,5 +74,40 @@ namespace Microsoft.AspNetCore.Hosting.Internal { WriteEvent(5); } + + internal void RequestFailed() + { + Interlocked.Increment(ref _failedRequests); + } + + protected override void OnEventCommand(EventCommandEventArgs command) + { + if (command.Command == EventCommand.Enable) + { + // 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) + { + DisplayName = "Request Rate", + DisplayRateTimeScale = TimeSpan.FromSeconds(1) + }; + + _totalRequestsCounter ??= new PollingCounter("total-requests", this, () => _totalRequests) + { + DisplayName = "Total Requests", + }; + + _currentRequestsCounter ??= new PollingCounter("current-requests", this, () => _currentRequests) + { + DisplayName = "Current Requests" + }; + + _failedRequestsCounter ??= new PollingCounter("failed-requests", this, () => _failedRequests) + { + DisplayName = "Failed Requests" + }; + } + } } } diff --git a/src/Hosting/Hosting/test/Internal/AsyncEnumerableExtensions.cs b/src/Hosting/Hosting/test/Internal/AsyncEnumerableExtensions.cs new file mode 100644 index 0000000000..c51ab06bbe --- /dev/null +++ b/src/Hosting/Hosting/test/Internal/AsyncEnumerableExtensions.cs @@ -0,0 +1,23 @@ +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Collections.Generic +{ + internal static class AsyncEnumerableExtensions + { + public static async Task FirstOrDefault(this IAsyncEnumerator values, Func filter) + { + while (await values.MoveNextAsync()) + { + if (filter(values.Current)) + { + return values.Current; + } + } + + return default; + } + } +} diff --git a/src/Hosting/Hosting/test/Internal/HostingEventSourceTests.cs b/src/Hosting/Hosting/test/Internal/HostingEventSourceTests.cs index a32433720b..b3405a1e21 100644 --- a/src/Hosting/Hosting/test/Internal/HostingEventSourceTests.cs +++ b/src/Hosting/Hosting/test/Internal/HostingEventSourceTests.cs @@ -2,8 +2,11 @@ // 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.Tracing; -using System.Reflection; +using System.Threading; +using System.Threading.Channels; +using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing.xunit; @@ -17,16 +20,11 @@ namespace Microsoft.AspNetCore.Hosting.Internal public void MatchesNameAndGuid() { // Arrange & Act - var eventSourceType = typeof(WebHost).GetTypeInfo().Assembly.GetType( - "Microsoft.AspNetCore.Hosting.Internal.HostingEventSource", - throwOnError: true, - ignoreCase: false); + var eventSource = new HostingEventSource(); // Assert - Assert.NotNull(eventSourceType); - Assert.Equal("Microsoft-AspNetCore-Hosting", EventSource.GetName(eventSourceType)); - Assert.Equal(Guid.Parse("9e620d2a-55d4-5ade-deb7-c26046d245a8"), EventSource.GetGuid(eventSourceType)); - Assert.NotEmpty(EventSource.GenerateManifest(eventSourceType, "assemblyPathToIncludeInManifest")); + Assert.Equal("Microsoft.AspNetCore.Hosting", eventSource.Name); + Assert.Equal(Guid.Parse("9ded64a4-414c-5251-dcf7-1e4e20c15e70"), eventSource.Guid); } [Fact] @@ -35,7 +33,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal // Arrange var expectedEventId = 1; var eventListener = new TestEventListener(expectedEventId); - var hostingEventSource = HostingEventSource.Log; + var hostingEventSource = GetHostingEventSource(); eventListener.EnableEvents(hostingEventSource, EventLevel.Informational); // Act @@ -58,7 +56,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal // Arrange var expectedEventId = 2; var eventListener = new TestEventListener(expectedEventId); - var hostingEventSource = HostingEventSource.Log; + var hostingEventSource = GetHostingEventSource(); eventListener.EnableEvents(hostingEventSource, EventLevel.Informational); // Act @@ -115,7 +113,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal // Arrange var expectedEventId = 3; var eventListener = new TestEventListener(expectedEventId); - var hostingEventSource = HostingEventSource.Log; + var hostingEventSource = GetHostingEventSource(); eventListener.EnableEvents(hostingEventSource, EventLevel.Informational); // Act @@ -144,7 +142,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal // Arrange var expectedEventId = 4; var eventListener = new TestEventListener(expectedEventId); - var hostingEventSource = HostingEventSource.Log; + var hostingEventSource = GetHostingEventSource(); eventListener.EnableEvents(hostingEventSource, EventLevel.Informational); // Act @@ -166,7 +164,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal // Arrange var expectedEventId = 5; var eventListener = new TestEventListener(expectedEventId); - var hostingEventSource = HostingEventSource.Log; + var hostingEventSource = GetHostingEventSource(); eventListener.EnableEvents(hostingEventSource, EventLevel.Informational); // Act @@ -182,16 +180,65 @@ namespace Microsoft.AspNetCore.Hosting.Internal Assert.Empty(eventData.Payload); } - private static Exception GetException() + [Fact] + public async Task VerifyCountersFireWithCorrectValues() { - try - { - throw new InvalidOperationException("An invalid operation has occurred"); - } - catch (Exception ex) - { - return ex; - } + // Arrange + var eventListener = new CounterListener(new[] { + "requests-per-second", + "total-requests", + "current-requests", + "failed-requests" + }); + + var hostingEventSource = GetHostingEventSource(); + + using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)); + + var rpsValues = eventListener.GetCounterValues("requests-per-second", timeoutTokenSource.Token).GetAsyncEnumerator(); + var totalRequestValues = eventListener.GetCounterValues("total-requests", timeoutTokenSource.Token).GetAsyncEnumerator(); + var currentRequestValues = eventListener.GetCounterValues("current-requests", timeoutTokenSource.Token).GetAsyncEnumerator(); + var failedRequestValues = eventListener.GetCounterValues("failed-requests", timeoutTokenSource.Token).GetAsyncEnumerator(); + + eventListener.EnableEvents(hostingEventSource, EventLevel.Informational, EventKeywords.None, + new Dictionary + { + { "EventCounterIntervalSec", "1" } + }); + + hostingEventSource.RequestStart("GET", "/"); + + Assert.Equal(1, await totalRequestValues.FirstOrDefault(v => v == 1)); + Assert.Equal(1, await rpsValues.FirstOrDefault(v => v == 1)); + Assert.Equal(1, await currentRequestValues.FirstOrDefault(v => v == 1)); + Assert.Equal(0, await failedRequestValues.FirstOrDefault(v => v == 0)); + + hostingEventSource.RequestStop(); + + Assert.Equal(1, await totalRequestValues.FirstOrDefault(v => v == 1)); + Assert.Equal(0, await rpsValues.FirstOrDefault(v => v == 0)); + Assert.Equal(0, await currentRequestValues.FirstOrDefault(v => v == 0)); + Assert.Equal(0, await failedRequestValues.FirstOrDefault(v => v == 0)); + + hostingEventSource.RequestStart("POST", "/"); + + Assert.Equal(2, await totalRequestValues.FirstOrDefault(v => v == 2)); + Assert.Equal(1, await rpsValues.FirstOrDefault(v => v == 1)); + Assert.Equal(1, await currentRequestValues.FirstOrDefault(v => v == 1)); + Assert.Equal(0, await failedRequestValues.FirstOrDefault(v => v == 0)); + + hostingEventSource.RequestFailed(); + hostingEventSource.RequestStop(); + + Assert.Equal(2, await totalRequestValues.FirstOrDefault(v => v == 2)); + Assert.Equal(0, await rpsValues.FirstOrDefault(v => v == 0)); + Assert.Equal(0, await currentRequestValues.FirstOrDefault(v => v == 0)); + Assert.Equal(1, await failedRequestValues.FirstOrDefault(v => v == 1)); + } + + private static HostingEventSource GetHostingEventSource() + { + return new HostingEventSource(Guid.NewGuid().ToString()); } private class TestEventListener : EventListener @@ -216,5 +263,36 @@ namespace Microsoft.AspNetCore.Hosting.Internal } } } + + private class CounterListener : EventListener + { + private readonly Dictionary> _counters = new Dictionary>(); + + public CounterListener(string[] counterNames) + { + foreach (var item in counterNames) + { + _counters[item] = Channel.CreateUnbounded(); + } + } + + public IAsyncEnumerable GetCounterValues(string counterName, CancellationToken cancellationToken = default) + { + return _counters[counterName].Reader.ReadAllAsync(cancellationToken); + } + + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + if (eventData.EventName == "EventCounters") + { + var payload = (IDictionary)eventData.Payload[0]; + var counter = (string)payload["Name"]; + payload.TryGetValue("Increment", out var increment); + payload.TryGetValue("Mean", out var mean); + var writer = _counters[counter].Writer; + writer.TryWrite((double)(increment ?? mean)); + } + } + } } } diff --git a/src/Hosting/Hosting/test/Microsoft.AspNetCore.Hosting.Tests.csproj b/src/Hosting/Hosting/test/Microsoft.AspNetCore.Hosting.Tests.csproj index cfdfd4ed0c..10635b2859 100644 --- a/src/Hosting/Hosting/test/Microsoft.AspNetCore.Hosting.Tests.csproj +++ b/src/Hosting/Hosting/test/Microsoft.AspNetCore.Hosting.Tests.csproj @@ -19,6 +19,7 @@ + diff --git a/src/Identity/EntityFrameworkCore/src/UserOnlyStore.cs b/src/Identity/EntityFrameworkCore/src/UserOnlyStore.cs index c66b73f267..afff7ad106 100644 --- a/src/Identity/EntityFrameworkCore/src/UserOnlyStore.cs +++ b/src/Identity/EntityFrameworkCore/src/UserOnlyStore.cs @@ -312,8 +312,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore throw new ArgumentNullException(nameof(user)); } - // TODO: Fix once EF query works Issue #10668 - return (await UserClaims.Where(uc => uc.UserId.Equals(user.Id)).ToListAsync(cancellationToken)).Select(c => c.ToClaim()).ToList(); + return await UserClaims.Where(uc => uc.UserId.Equals(user.Id)).Select(c => c.ToClaim()).ToListAsync(cancellationToken); } /// diff --git a/src/Identity/EntityFrameworkCore/src/UserStore.cs b/src/Identity/EntityFrameworkCore/src/UserStore.cs index 1038297db6..62f6fe5271 100644 --- a/src/Identity/EntityFrameworkCore/src/UserStore.cs +++ b/src/Identity/EntityFrameworkCore/src/UserStore.cs @@ -445,8 +445,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore throw new ArgumentNullException(nameof(user)); } - // TODO: Fix once EF query works Issue #10668 - return (await UserClaims.Where(uc => uc.UserId.Equals(user.Id)).ToListAsync(cancellationToken)).Select(c => c.ToClaim()).ToList(); + return await UserClaims.Where(uc => uc.UserId.Equals(user.Id)).Select(c => c.ToClaim()).ToListAsync(cancellationToken); } /// diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/CustomPocoTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/CustomPocoTest.cs index 9f34074bdb..736451d58a 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/CustomPocoTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/CustomPocoTest.cs @@ -29,9 +29,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanUpdateNameGuid() { using (var db = new CustomDbContext( @@ -54,9 +51,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanUpdateNameString() { using (var db = new CustomDbContext( @@ -79,9 +73,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanCreateUserInt() { using (var db = new CustomDbContext( @@ -102,9 +93,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanCreateUserIntViaSet() { using (var db = new CustomDbContext( @@ -126,9 +114,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanUpdateNameInt() { using (var db = new CustomDbContext( @@ -151,9 +136,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanUpdateNameIntWithSet() { using (var db = new CustomDbContext( diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/DbUtil.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/DbUtil.cs index 5dd8195227..46255b9cec 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/DbUtil.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/DbUtil.cs @@ -44,11 +44,9 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test { var count = 0; - // TODO: Use new API once EF is updated. Issue #10671 - foreach (var property in context.Model.GetEntityTypes().Single(e => (string)e.FindAnnotation("Relational:TableName")?.Value == table).GetProperties()) + foreach (var property in context.Model.GetEntityTypes().Single(e => e.GetTableName() == table).GetProperties()) { - // TODO: Use new API once EF is updated. Issue #10671 - if (!columns.Contains((string)property.FindAnnotation("Relational:ColumnName")?.Value ?? property.Name)) + if (!columns.Contains(property.GetColumnName())) { continue; } diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/DefaultPocoTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/DefaultPocoTest.cs index 98f97df0d4..f6852e079f 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/DefaultPocoTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/DefaultPocoTest.cs @@ -16,7 +16,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test public class DefaultPocoTest : IClassFixture { private readonly ApplicationBuilder _builder; - private const string DatabaseName = nameof(DefaultPocoTest); public DefaultPocoTest(ScratchDatabaseFixture fixture) { @@ -42,9 +41,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task EnsureStartupUsageWorks() { var userStore = _builder.ApplicationServices.GetRequiredService>(); diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/MaxKeyLengthSchemaTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/MaxKeyLengthSchemaTest.cs index 55d18b1f8c..8b9bef2469 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/MaxKeyLengthSchemaTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/MaxKeyLengthSchemaTest.cs @@ -15,7 +15,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test public class MaxKeyLengthSchemaTest : IClassFixture { private readonly ApplicationBuilder _builder; - private const string DatabaseName = nameof(MaxKeyLengthSchemaTest); public MaxKeyLengthSchemaTest(ScratchDatabaseFixture fixture) { @@ -49,9 +48,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public void EnsureDefaultSchema() { using (var scope = _builder.ApplicationServices.GetRequiredService().CreateScope()) diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.csproj b/src/Identity/EntityFrameworkCore/test/EF.Test/Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.csproj index d3dffb3d0b..8f724760cb 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.csproj +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test.csproj @@ -1,10 +1,7 @@ - + netcoreapp3.0 - - - true diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs index c0b0c49225..ee7e762019 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreOnlyUsersTestBase.cs @@ -2,13 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Data.SqlClient; using System.Linq; using System.Linq.Expressions; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity.Test; -using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing.xunit; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; @@ -73,9 +71,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public void EnsureDefaultSchema() { VerifyDefaultSchema(CreateContext()); @@ -107,9 +102,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task DeleteUserRemovesTokensTest() { // Need fail if not empty? @@ -127,9 +119,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public void CanCreateUserUsingEF() { using (var db = CreateContext()) @@ -143,9 +132,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanCreateUsingManager() { var manager = CreateManager(); @@ -172,9 +158,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task LoadFromDbFindByIdTest() { var db = CreateContext(); @@ -191,9 +174,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task LoadFromDbFindByNameTest() { var db = CreateContext(); @@ -209,9 +189,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task LoadFromDbFindByLoginTest() { var db = CreateContext(); @@ -227,9 +204,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task LoadFromDbFindByEmailTest() { var db = CreateContext(); diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs index d889876dcc..14ab7db642 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/SqlStoreTestBase.cs @@ -2,13 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Data.SqlClient; using System.Linq; using System.Linq.Expressions; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity.Test; -using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing.xunit; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; @@ -120,9 +118,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public void EnsureDefaultSchema() { VerifyDefaultSchema(CreateContext()); @@ -155,9 +150,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task DeleteRoleNonEmptySucceedsTest() { // Need fail if not empty? @@ -183,9 +175,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task DeleteUserRemovesFromRoleTest() { // Need fail if not empty? @@ -209,9 +198,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task DeleteUserRemovesTokensTest() { // Need fail if not empty? @@ -229,9 +215,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public void CanCreateUserUsingEF() { using (var db = CreateContext()) @@ -245,9 +228,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanCreateUsingManager() { var manager = CreateManager(); @@ -281,9 +261,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task LoadFromDbFindByIdTest() { var db = CreateContext(); @@ -300,9 +277,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task LoadFromDbFindByNameTest() { var db = CreateContext(); @@ -318,9 +292,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task LoadFromDbFindByLoginTest() { var db = CreateContext(); @@ -336,9 +307,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task GetSecurityStampThrowsIfNull() { var manager = CreateManager(); @@ -350,9 +318,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task LoadFromDbFindByEmailTest() { var db = CreateContext(); diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyCustomContextTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyCustomContextTest.cs index 14eb1a77ee..1ef282f03d 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyCustomContextTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyCustomContextTest.cs @@ -16,7 +16,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test public class UserOnlyCustomContextTest : IClassFixture { private readonly ApplicationBuilder _builder; - private const string DatabaseName = nameof(UserOnlyCustomContextTest); public class CustomContext : DbContext { @@ -87,9 +86,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task EnsureStartupUsageWorks() { var userStore = _builder.ApplicationServices.GetRequiredService>(); diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyTest.cs index 4fa6c005cb..c17c6ad53e 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserOnlyTest.cs @@ -17,7 +17,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test public class UserOnlyTest : IClassFixture { private readonly ApplicationBuilder _builder; - private const string DatabaseName = nameof(UserOnlyTest); public class TestUserDbContext : IdentityUserContext { @@ -49,9 +48,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task EnsureStartupUsageWorks() { var userStore = _builder.ApplicationServices.GetRequiredService>(); @@ -68,9 +64,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task FindByEmailThrowsWithTwoUsersWithSameEmail() { var userStore = _builder.ApplicationServices.GetRequiredService>(); diff --git a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs index 21a2c34446..6839a0c71e 100644 --- a/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs +++ b/src/Identity/EntityFrameworkCore/test/EF.Test/UserStoreTest.cs @@ -7,7 +7,6 @@ using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity.Test; using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.AspNetCore.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Xunit; @@ -30,9 +29,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public void CanCreateUserUsingEF() { using (var db = CreateContext()) @@ -167,9 +163,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanCreateUsingManager() { var manager = CreateManager(); @@ -180,9 +173,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task TwoUsersSamePasswordDifferentHash() { var manager = CreateManager(); @@ -195,9 +185,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task FindByEmailThrowsWithTwoUsersWithSameEmail() { var manager = CreateManager(); @@ -212,9 +199,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task AddUserToUnknownRoleFails() { var manager = CreateManager(); @@ -225,9 +209,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ConcurrentUpdatesWillFail() { var options = new DbContextOptionsBuilder().UseSqlite($"Data Source=D{Guid.NewGuid()}.db").Options; @@ -259,9 +240,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ConcurrentUpdatesWillFailWithDetachedUser() { var options = new DbContextOptionsBuilder().UseSqlite($"Data Source=D{Guid.NewGuid()}.db").Options; @@ -291,9 +269,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task DeleteAModifiedUserWillFail() { var options = new DbContextOptionsBuilder().UseSqlite($"Data Source=D{Guid.NewGuid()}.db").Options; @@ -324,9 +299,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ConcurrentRoleUpdatesWillFail() { var options = new DbContextOptionsBuilder().UseSqlite($"Data Source=D{Guid.NewGuid()}.db").Options; @@ -358,9 +330,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ConcurrentRoleUpdatesWillFailWithDetachedRole() { var options = new DbContextOptionsBuilder().UseSqlite($"Data Source=D{Guid.NewGuid()}.db").Options; @@ -391,9 +360,6 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] public async Task DeleteAModifiedRoleWillFail() { var options = new DbContextOptionsBuilder().UseSqlite($"Data Source=D{Guid.NewGuid()}.db").Options; diff --git a/src/Identity/test/Identity.Test/UserManagerTest.cs b/src/Identity/test/Identity.Test/UserManagerTest.cs index f5c6e938a8..37cecb047c 100644 --- a/src/Identity/test/Identity.Test/UserManagerTest.cs +++ b/src/Identity/test/Identity.Test/UserManagerTest.cs @@ -979,7 +979,6 @@ namespace Microsoft.AspNetCore.Identity.Test [Fact] public async Task PasswordValidatorBlocksCreate() { - // TODO: Can switch to Mock eventually var manager = MockHelpers.TestUserManager(new EmptyStore()); manager.PasswordValidators.Clear(); manager.PasswordValidators.Add(new BadPasswordValidator(true)); @@ -990,7 +989,6 @@ namespace Microsoft.AspNetCore.Identity.Test [Fact] public async Task PasswordValidatorWithoutErrorsBlocksCreate() { - // TODO: Can switch to Mock eventually var manager = MockHelpers.TestUserManager(new EmptyStore()); manager.PasswordValidators.Clear(); manager.PasswordValidators.Add(new BadPasswordValidator()); diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj index a900f6d5e0..fc7b1609b7 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj +++ b/src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.vcxproj @@ -42,7 +42,7 @@ DynamicLibrary - v141 + v142 Unicode diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/IISSetup.CommonLib.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/IISSetup.CommonLib.vcxproj index 92295eb9db..bc5eb5365c 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/IISSetup.CommonLib.vcxproj +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/lib/IISSetup.CommonLib.vcxproj @@ -31,7 +31,7 @@ StaticLibrary - v141 + v142 false diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj index 257df53c47..8d1093181d 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/IIS-Common/reftrace/reftrace.vcxproj @@ -47,7 +47,7 @@ StaticLibrary - v141 + v142 true diff --git a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj index f823e017c8..1f694316af 100644 --- a/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj +++ b/src/Installers/Windows/AspNetCoreModule-Setup/IIS-Setup/iisca/lib/iisca.vcxproj @@ -74,7 +74,7 @@ StaticLibrary Unicode - v141 + v142 diff --git a/src/Mvc/Mvc.Core/src/ControllerBase.cs b/src/Mvc/Mvc.Core/src/ControllerBase.cs index 359b43c14d..1bca7a09f3 100644 --- a/src/Mvc/Mvc.Core/src/ControllerBase.cs +++ b/src/Mvc/Mvc.Core/src/ControllerBase.cs @@ -212,12 +212,10 @@ namespace Microsoft.AspNetCore.Mvc [NonAction] public virtual ObjectResult StatusCode([ActionResultStatusCode] int statusCode, [ActionResultObjectValue] object value) { - var result = new ObjectResult(value) + return new ObjectResult(value) { StatusCode = statusCode }; - - return result; } /// @@ -270,13 +268,11 @@ namespace Microsoft.AspNetCore.Mvc [NonAction] public virtual ContentResult Content(string content, MediaTypeHeaderValue contentType) { - var result = new ContentResult + return new ContentResult { Content = content, ContentType = contentType?.ToString() }; - - return result; } /// @@ -1772,9 +1768,7 @@ namespace Microsoft.AspNetCore.Mvc /// The created for the response. [NonAction] public virtual UnprocessableEntityResult UnprocessableEntity() - { - return new UnprocessableEntityResult(); - } + => new UnprocessableEntityResult(); /// /// Creates an that produces a response. @@ -1783,9 +1777,7 @@ namespace Microsoft.AspNetCore.Mvc /// The created for the response. [NonAction] public virtual UnprocessableEntityObjectResult UnprocessableEntity([ActionResultObjectValue] object error) - { - return new UnprocessableEntityObjectResult(error); - } + => new UnprocessableEntityObjectResult(error); /// /// Creates an that produces a response. diff --git a/src/Mvc/Mvc.Core/src/PhysicalFileResult.cs b/src/Mvc/Mvc.Core/src/PhysicalFileResult.cs index 27a02b4d94..c3c8e5f35b 100644 --- a/src/Mvc/Mvc.Core/src/PhysicalFileResult.cs +++ b/src/Mvc/Mvc.Core/src/PhysicalFileResult.cs @@ -41,12 +41,7 @@ namespace Microsoft.AspNetCore.Mvc public PhysicalFileResult(string fileName, MediaTypeHeaderValue contentType) : base(contentType?.ToString()) { - if (fileName == null) - { - throw new ArgumentNullException(nameof(fileName)); - } - - FileName = fileName; + FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); } /// @@ -55,15 +50,7 @@ namespace Microsoft.AspNetCore.Mvc public string FileName { get => _fileName; - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - _fileName = value; - } + set => _fileName = value ?? throw new ArgumentNullException(nameof(value)); } /// diff --git a/src/Mvc/Mvc.Core/src/ProducesAttribute.cs b/src/Mvc/Mvc.Core/src/ProducesAttribute.cs index 41d1815bd9..24218189e5 100644 --- a/src/Mvc/Mvc.Core/src/ProducesAttribute.cs +++ b/src/Mvc/Mvc.Core/src/ProducesAttribute.cs @@ -25,13 +25,8 @@ namespace Microsoft.AspNetCore.Mvc /// /// The of object that is going to be written in the response. public ProducesAttribute(Type type) - { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - - Type = type; + { + Type = type ?? throw new ArgumentNullException(nameof(type)); ContentTypes = new MediaTypeCollection(); } diff --git a/src/Mvc/Mvc.Core/src/ProducesResponseTypeAttribute.cs b/src/Mvc/Mvc.Core/src/ProducesResponseTypeAttribute.cs index 7c0d25c6a4..2af82b4ef6 100644 --- a/src/Mvc/Mvc.Core/src/ProducesResponseTypeAttribute.cs +++ b/src/Mvc/Mvc.Core/src/ProducesResponseTypeAttribute.cs @@ -29,12 +29,7 @@ namespace Microsoft.AspNetCore.Mvc /// The HTTP response status code. public ProducesResponseTypeAttribute(Type type, int statusCode) { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - - Type = type; + Type = type ?? throw new ArgumentNullException(nameof(type)); StatusCode = statusCode; } diff --git a/src/Mvc/Mvc.Core/src/RouteAttribute.cs b/src/Mvc/Mvc.Core/src/RouteAttribute.cs index db42bd2bc1..cc17d61799 100644 --- a/src/Mvc/Mvc.Core/src/RouteAttribute.cs +++ b/src/Mvc/Mvc.Core/src/RouteAttribute.cs @@ -20,12 +20,7 @@ namespace Microsoft.AspNetCore.Mvc /// The route template. May not be null. public RouteAttribute(string template) { - if (template == null) - { - throw new ArgumentNullException(nameof(template)); - } - - Template = template; + Template = template ?? throw new ArgumentNullException(nameof(template)); } /// diff --git a/src/Mvc/Mvc.Core/src/ServiceFilterAttribute.cs b/src/Mvc/Mvc.Core/src/ServiceFilterAttribute.cs index 9e16cb4715..e9d69ff292 100644 --- a/src/Mvc/Mvc.Core/src/ServiceFilterAttribute.cs +++ b/src/Mvc/Mvc.Core/src/ServiceFilterAttribute.cs @@ -30,12 +30,7 @@ namespace Microsoft.AspNetCore.Mvc /// The of filter to find. public ServiceFilterAttribute(Type type) { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - - ServiceType = type; + ServiceType = type ?? throw new ArgumentNullException(nameof(type)); } /// diff --git a/src/Mvc/Mvc.Core/src/SignInResult.cs b/src/Mvc/Mvc.Core/src/SignInResult.cs index d7bdfd3867..0f0ba36f20 100644 --- a/src/Mvc/Mvc.Core/src/SignInResult.cs +++ b/src/Mvc/Mvc.Core/src/SignInResult.cs @@ -35,19 +35,9 @@ namespace Microsoft.AspNetCore.Mvc /// The claims principal containing the user claims. /// used to perform the sign-in operation. public SignInResult(string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties) - { - if (authenticationScheme == null) - { - throw new ArgumentNullException(nameof(authenticationScheme)); - } - - if (principal == null) - { - throw new ArgumentNullException(nameof(principal)); - } - - AuthenticationScheme = authenticationScheme; - Principal = principal; + { + AuthenticationScheme = authenticationScheme ?? throw new ArgumentNullException(nameof(authenticationScheme)); + Principal = principal ?? throw new ArgumentNullException(nameof(principal)); Properties = properties; } diff --git a/src/Mvc/Mvc.Core/src/SignOutResult.cs b/src/Mvc/Mvc.Core/src/SignOutResult.cs index 0f69354784..61a9331bab 100644 --- a/src/Mvc/Mvc.Core/src/SignOutResult.cs +++ b/src/Mvc/Mvc.Core/src/SignOutResult.cs @@ -62,13 +62,8 @@ namespace Microsoft.AspNetCore.Mvc /// The authentication scheme to use when signing out the user. /// used to perform the sign-out operation. public SignOutResult(IList authenticationSchemes, AuthenticationProperties properties) - { - if (authenticationSchemes == null) - { - throw new ArgumentNullException(nameof(authenticationSchemes)); - } - - AuthenticationSchemes = authenticationSchemes; + { + AuthenticationSchemes = authenticationSchemes ?? throw new ArgumentNullException(nameof(authenticationSchemes)); Properties = properties; } diff --git a/src/Mvc/Mvc.Core/src/TypeFilterAttribute.cs b/src/Mvc/Mvc.Core/src/TypeFilterAttribute.cs index a2048512a6..eeef33c374 100644 --- a/src/Mvc/Mvc.Core/src/TypeFilterAttribute.cs +++ b/src/Mvc/Mvc.Core/src/TypeFilterAttribute.cs @@ -34,12 +34,7 @@ namespace Microsoft.AspNetCore.Mvc /// The of filter to create. public TypeFilterAttribute(Type type) { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - - ImplementationType = type; + ImplementationType = type ?? throw new ArgumentNullException(nameof(type)); } /// diff --git a/src/Mvc/Mvc.Core/src/VirtualFileResult.cs b/src/Mvc/Mvc.Core/src/VirtualFileResult.cs index b7743795a0..af075b5a09 100644 --- a/src/Mvc/Mvc.Core/src/VirtualFileResult.cs +++ b/src/Mvc/Mvc.Core/src/VirtualFileResult.cs @@ -43,12 +43,7 @@ namespace Microsoft.AspNetCore.Mvc public VirtualFileResult(string fileName, MediaTypeHeaderValue contentType) : base(contentType?.ToString()) { - if (fileName == null) - { - throw new ArgumentNullException(nameof(fileName)); - } - - FileName = fileName; + FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); } /// @@ -56,19 +51,8 @@ namespace Microsoft.AspNetCore.Mvc /// public string FileName { - get - { - return _fileName; - } - set - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - _fileName = value; - } + get => _fileName; + set => _fileName = value ?? throw new ArgumentNullException(nameof(value)); } /// diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.ts b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.ts index d98208a724..b48738b645 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.ts +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/login/login.component.ts @@ -53,7 +53,7 @@ export class LoginComponent implements OnInit { switch (result.status) { case AuthenticationResultStatus.Redirect: // We replace the location here so that in case the user hits the back - // arrow from within the login page he doesn't get into an infinite + // arrow from within the login page they don't get into an infinite // redirect loop. window.location.replace(result.redirectUrl); break; @@ -120,7 +120,7 @@ export class LoginComponent implements OnInit { private redirectToApiAuthorizationPath(apiAuthorizationPath: string) { // It's important that we do a replace here so that when the user hits the back arrow on the - // browser he gets sent back to where it was on the app instead of to an endpoint on this + // browser they get sent back to where it was on the app instead of to an endpoint on this // component. const redirectUrl = `${window.location.origin}${apiAuthorizationPath}`; window.location.replace(redirectUrl); diff --git a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.ts b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.ts index d58362c711..d9402f007e 100644 --- a/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.ts +++ b/src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/ClientApp/src/api-authorization/logout/logout.component.ts @@ -54,7 +54,7 @@ export class LogoutComponent implements OnInit { switch (result.status) { case AuthenticationResultStatus.Redirect: // We replace the location here so that in case the user hits the back - // arrow from within the IdP he doesn't get into an infinite redirect loop. + // arrow from within the IdP they don't get into an infinite redirect loop. window.location.replace(result.redirectUrl); break; case AuthenticationResultStatus.Success: diff --git a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp index cb4893196f..bb42023988 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp @@ -64,6 +64,7 @@ HandlerResolver::LoadRequestHandlerAssembly(const IHttpApplication &pApplication pConfiguration.QueryProcessPath(), pApplication.GetApplicationPhysicalPath(), pConfiguration.QueryArguments(), + errorContext, options)); location = options->GetDotnetExeLocation(); diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj index 8816dafbda..626abc70e4 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/CommonLib.vcxproj @@ -196,6 +196,7 @@ + @@ -245,7 +246,6 @@ - @@ -279,4 +279,4 @@ - \ No newline at end of file + diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ErrorContext.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ErrorContext.h new file mode 100644 index 0000000000..aa53a8249f --- /dev/null +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ErrorContext.h @@ -0,0 +1,14 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +#pragma once + +struct ErrorContext +{ + // TODO consider adding HRESULT here + std::string detailedErrorContent; + USHORT statusCode; + USHORT subStatusCode; + std::string generalErrorType; + std::string errorReason; +}; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HandleWrapper.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HandleWrapper.cpp deleted file mode 100644 index 4960b06f4e..0000000000 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HandleWrapper.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// 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. - -#include "HandleWrapper.h" - -// Workaround for VC++ bug https://developercommunity.visualstudio.com/content/problem/33928/constexpr-failing-on-nullptr-v141-compiler-regress.html -const HANDLE InvalidHandleTraits::DefaultHandle = INVALID_HANDLE_VALUE; -const HANDLE FindFileHandleTraits::DefaultHandle = INVALID_HANDLE_VALUE; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HandleWrapper.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HandleWrapper.h index 56da4ae035..9e93d1e42b 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HandleWrapper.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HandleWrapper.h @@ -9,7 +9,7 @@ struct InvalidHandleTraits { using HandleType = HANDLE; - static const HANDLE DefaultHandle; + static constexpr HANDLE DefaultHandle = nullptr; static void Close(HANDLE handle) noexcept { CloseHandle(handle); } }; @@ -23,7 +23,7 @@ struct NullHandleTraits struct FindFileHandleTraits { using HandleType = HANDLE; - static const HANDLE DefaultHandle; + static constexpr HANDLE DefaultHandle = nullptr; static void Close(HANDLE handle) noexcept { FindClose(handle); } }; @@ -35,16 +35,16 @@ struct ModuleHandleTraits }; // Code analysis doesn't like nullptr usages via traits -#pragma warning( push ) -#pragma warning ( disable : 26477 ) // disable Use 'nullptr' rather than 0 or NULL (es.47). +#pragma warning(push) +#pragma warning(disable : 26477) // disable Use 'nullptr' rather than 0 or NULL (es.47). -template +template class HandleWrapper { public: using HandleType = typename traits::HandleType; - HandleWrapper(HandleType handle = traits::DefaultHandle) noexcept : m_handle(handle) { } + HandleWrapper(HandleType handle = traits::DefaultHandle) noexcept : m_handle(handle) {} ~HandleWrapper() { if (m_handle != traits::DefaultHandle) @@ -54,14 +54,14 @@ public: } operator HandleType() noexcept { return m_handle; } - HandleWrapper& operator =(HandleType value) noexcept + HandleWrapper &operator=(HandleType value) noexcept { DBG_ASSERT(m_handle == traits::DefaultHandle); m_handle = value; return *this; } - HandleType* operator&() noexcept { return &m_handle; } + HandleType *operator&() noexcept { return &m_handle; } HandleType release() noexcept { @@ -74,4 +74,4 @@ private: HandleType m_handle; }; -#pragma warning( pop ) +#pragma warning(pop) diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h index ccd8fff54f..526222322e 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h @@ -28,16 +28,6 @@ typedef int(*hostfxr_set_runtime_property_value_fn)(void* host_context_handle, P typedef int(*hostfxr_run_app_fn)(void* host_context_handle); typedef int(*hostfxr_close_fn)(void* hostfxr_context_handle); -struct ErrorContext -{ - // TODO consider adding HRESULT here - std::string detailedErrorContent; - USHORT statusCode; - USHORT subStatusCode; - std::string generalErrorType; - std::string errorReason; -}; - class HostFxrErrorRedirector: NonCopyable { public: diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolutionResult.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolutionResult.cpp index 269aec7660..9a80749f2c 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolutionResult.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolutionResult.cpp @@ -23,6 +23,7 @@ HRESULT HostFxrResolutionResult::Create( _In_ const std::wstring& pcwzProcessPath, _In_ const std::wstring& pcwzApplicationPhysicalPath, _In_ const std::wstring& pcwzArguments, + _In_ ErrorContext& errorContext, _Out_ std::unique_ptr& ppWrapper) { std::filesystem::path knownDotnetLocation; @@ -42,7 +43,8 @@ HRESULT HostFxrResolutionResult::Create( pcwzArguments, hostFxrDllPath, knownDotnetLocation, - arguments); + arguments, + errorContext); LOG_INFOF(L"Parsed hostfxr options: dotnet location: '%ls' hostfxr path: '%ls' arguments:", knownDotnetLocation.c_str(), hostFxrDllPath.c_str()); for (size_t i = 0; i < arguments.size(); i++) diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolutionResult.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolutionResult.h index 25b502fc15..a0bbf17003 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolutionResult.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolutionResult.h @@ -10,6 +10,8 @@ #include #include +#include "ErrorContext.h" + class HostFxrResolutionResult { public: @@ -44,6 +46,7 @@ public: _In_ const std::wstring& pcwzProcessPath, _In_ const std::wstring& pcwzApplicationPhysicalPath, _In_ const std::wstring& pcwzArguments, + _In_ ErrorContext& errorContext, _Out_ std::unique_ptr& ppWrapper); private: diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp index e6bfdfb0c6..45e3699fad 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp @@ -21,7 +21,8 @@ HostFxrResolver::GetHostFxrParameters( const std::wstring &applicationArguments, fs::path &hostFxrDllPath, fs::path &dotnetExePath, - std::vector &arguments + std::vector &arguments, + ErrorContext& errorContext ) { LOG_INFOF(L"Resolving hostfxr parameters for application: '%ls' arguments: '%ls' path: '%ls'", @@ -93,7 +94,13 @@ HostFxrResolver::GetHostFxrParameters( LOG_INFOF(L"Checking application.dll at '%ls'", applicationDllPath.c_str()); if (!is_regular_file(applicationDllPath)) { - throw InvalidOperationException(format(L"Application .dll was not found at %s", applicationDllPath.c_str())); + errorContext.subStatusCode = 38; + errorContext.errorReason = "Application DLL not found. Confirm the application dll is present. Single-file deployments are not supported in IIS."; + errorContext.generalErrorType = "ANCM Application DLL Not Found"; + errorContext.detailedErrorContent = format("Application DLL was not found at %s.", to_multi_byte_string(applicationDllPath, CP_UTF8).c_str()); + throw InvalidOperationException( + format(L"Application DLL was not found at %s. Confirm the application dll is present. Single-file deployments are not supported in IIS.", + applicationDllPath.c_str())); } hostFxrDllPath = executablePath.parent_path() / "hostfxr.dll"; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h index 1ff9ac8d14..70f63fca6f 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h @@ -9,6 +9,8 @@ #include #include +#include "ErrorContext.h" + #define READ_BUFFER_SIZE 4096 class HostFxrResolver @@ -23,7 +25,8 @@ public: const std::wstring &applicationArguments, std::filesystem::path &hostFxrDllPath, std::filesystem::path &dotnetExePath, - std::vector &arguments + std::vector &arguments, + ErrorContext& errorContext ); static diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLibTests/CommonLibTests.vcxproj b/src/Servers/IIS/AspNetCoreModuleV2/CommonLibTests/CommonLibTests.vcxproj index 46dd0a68c4..7268908ebd 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLibTests/CommonLibTests.vcxproj +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLibTests/CommonLibTests.vcxproj @@ -43,7 +43,6 @@ - @@ -187,4 +186,4 @@ true - + \ No newline at end of file diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLibTests/hostfxr_utility_tests.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLibTests/hostfxr_utility_tests.cpp deleted file mode 100644 index 31ddd86dc4..0000000000 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLibTests/hostfxr_utility_tests.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// 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. - -#include "stdafx.h" -#include -#include -#include -#include "HostFxrResolver.h" -#include "Environment.h" - -TEST(ParseHostFxrArguments, BasicHostFxrArguments) -{ - std::vector bstrArray; - - HostFxrResolver::AppendArguments( - L"exec \"test.dll\"", // args - L"invalid", // physical path to application - bstrArray); // args array. - - EXPECT_EQ(2, bstrArray.size()); - ASSERT_STREQ(L"exec", bstrArray[0].c_str()); - ASSERT_STREQ(L"test.dll", bstrArray[1].c_str()); -} - -TEST(ParseHostFxrArguments, NoExecProvided) -{ - std::vector bstrArray; - - HostFxrResolver::AppendArguments( - L"test.dll", // args - L"ignored", // physical path to application - bstrArray); // args array. - - EXPECT_EQ(1, bstrArray.size()); - ASSERT_STREQ(L"test.dll", bstrArray[0].c_str()); -} - -TEST(ParseHostFxrArguments, ConvertDllToAbsolutePath) -{ - std::vector bstrArray; - // we need to use existing dll so let's use ntdll that we know exists everywhere - auto system32 = Environment::ExpandEnvironmentVariables(L"%WINDIR%\\System32"); - HostFxrResolver::AppendArguments( - L"exec \"ntdll.dll\"", // args - system32, // physical path to application - bstrArray, // args array. - true); // expandDllPaths - - EXPECT_EQ(2, bstrArray.size()); - ASSERT_STREQ(L"exec", bstrArray[0].c_str()); - ASSERT_STREQ((system32 + L"\\ntdll.dll").c_str(), bstrArray[1].c_str()); -} - -TEST(ParseHostFxrArguments, ProvideNoArgs_InvalidArgs) -{ - std::vector bstrArray; - std::filesystem::path struHostFxrDllLocation; - std::filesystem::path struExeLocation; - - EXPECT_THROW(HostFxrResolver::GetHostFxrParameters( - L"dotnet", // processPath - L"some\\path", // application physical path, ignored. - L"", //arguments - struHostFxrDllLocation, - struExeLocation, - bstrArray), // args array. - InvalidOperationException); -} - -TEST(GetAbsolutePathToDotnetFromProgramFiles, BackupWorks) -{ - STRU struAbsolutePathToDotnet; - BOOL fDotnetInProgramFiles; - BOOL is64Bit; - BOOL fIsWow64 = FALSE; - SYSTEM_INFO systemInfo; - IsWow64Process(GetCurrentProcess(), &fIsWow64); - if (fIsWow64) - { - is64Bit = FALSE; - } - else - { - GetNativeSystemInfo(&systemInfo); - is64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; - } - - if (is64Bit) - { - fDotnetInProgramFiles = std::filesystem::is_regular_file(L"C:/Program Files/dotnet/dotnet.exe"); - } - else - { - fDotnetInProgramFiles = std::filesystem::is_regular_file(L"C:/Program Files (x86)/dotnet/dotnet.exe"); - } - - auto dotnetPath = HostFxrResolver::GetAbsolutePathToDotnetFromProgramFiles(); - if (fDotnetInProgramFiles) - { - EXPECT_TRUE(dotnetPath.has_value()); - } - else - { - EXPECT_FALSE(dotnetPath.has_value()); - } -} - -TEST(GetHostFxrArguments, InvalidParams) -{ - std::vector bstrArray; - std::filesystem::path struHostFxrDllLocation; - std::filesystem::path struExeLocation; - - EXPECT_THROW(HostFxrResolver::GetHostFxrParameters( - L"bogus", // processPath - L"", // application physical path, ignored. - L"ignored", //arguments - struHostFxrDllLocation, - struExeLocation, - bstrArray), // args array. - InvalidOperationException); -} diff --git a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp index cbc741959d..5707e4cd77 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp @@ -195,6 +195,8 @@ IN_PROCESS_APPLICATION::ExecuteApplication() auto context = std::make_shared(); + ErrorContext errorContext; // unused + if (s_fMainCallback == nullptr) { THROW_IF_FAILED(HostFxrResolutionResult::Create( @@ -202,6 +204,7 @@ IN_PROCESS_APPLICATION::ExecuteApplication() m_pConfig->QueryProcessPath(), QueryApplicationPhysicalPath(), m_pConfig->QueryArguments(), + errorContext, hostFxrResolutionResult )); diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs index 62b9ea0d1f..11467d4424 100644 --- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs +++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs @@ -365,6 +365,24 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessFailedToFindNativeDependencies(deploymentResult), Logger); } + [ConditionalFact] + public async Task SingleExecutable_FailedToFindNativeDependencies() + { + var deploymentParameters = Fixture.GetBaseDeploymentParameters(Fixture.InProcessTestSite); + deploymentParameters.ApplicationType = ApplicationType.Standalone; + var deploymentResult = await DeployAsync(deploymentParameters); + + File.Delete(Path.Combine(deploymentResult.ContentRoot, "InProcessWebSite.dll")); + if (DeployerSelector.HasNewShim) + { + await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult, "HTTP Error 500.38 - ANCM Application DLL Not Found"); + } + else + { + await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult); + } + } + [ConditionalFact] public async Task TargedDifferenceSharedFramework_FailedToFindNativeDependenciesErrorInResponse() { diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/Helpers.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/Helpers.cs index a790d38b26..6fbd3f6950 100644 --- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/Helpers.cs +++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/Helpers.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests public static string GetInProcessTestSitesName() { - return DeployerSelector.IsForwardsCompatibilityTest ? "InProcessForwardsCompatWebSite" : "InProcessWebSite"; + return DeployerSelector.IsNewShimTest ? "InProcessNewShimWebSite" : "InProcessWebSite"; } public static async Task AssertStarts(this IISDeploymentResult deploymentResult, string path = "/HelloWorld") diff --git a/src/Servers/IIS/IIS/test/IIS.FunctionalTests/DeployerSelector.cs b/src/Servers/IIS/IIS/test/IIS.FunctionalTests/DeployerSelector.cs index 6f15410e55..58353613fc 100644 --- a/src/Servers/IIS/IIS/test/IIS.FunctionalTests/DeployerSelector.cs +++ b/src/Servers/IIS/IIS/test/IIS.FunctionalTests/DeployerSelector.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests public static class DeployerSelector { public static ServerType ServerType => ServerType.IIS; - public static bool IsForwardsCompatibilityTest => false; + public static bool IsNewShimTest => false; public static bool HasNewShim => true; public static bool HasNewHandler => true; } diff --git a/src/Servers/IIS/IIS/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj b/src/Servers/IIS/IIS/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj index f95e32bb3e..2ecd5ba424 100644 --- a/src/Servers/IIS/IIS/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj +++ b/src/Servers/IIS/IIS/test/IIS.FunctionalTests/IIS.FunctionalTests.csproj @@ -12,8 +12,6 @@ - - False diff --git a/src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/DeployerSelector.cs b/src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/DeployerSelector.cs similarity index 88% rename from src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/DeployerSelector.cs rename to src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/DeployerSelector.cs index bdbcad2780..41a363f6cd 100644 --- a/src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/DeployerSelector.cs +++ b/src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/DeployerSelector.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests public static class DeployerSelector { public static ServerType ServerType => ServerType.IIS; - public static bool IsForwardsCompatibilityTest => false; + public static bool IsNewShimTest => false; public static bool HasNewShim => false; public static bool HasNewHandler => true; } diff --git a/src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/IIS.BackwardsCompatibility.FunctionalTests.csproj b/src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/IIS.NewHandler.FunctionalTests.csproj similarity index 64% rename from src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/IIS.BackwardsCompatibility.FunctionalTests.csproj rename to src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/IIS.NewHandler.FunctionalTests.csproj index 6b92406b14..f57d292b78 100644 --- a/src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/IIS.BackwardsCompatibility.FunctionalTests.csproj +++ b/src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/IIS.NewHandler.FunctionalTests.csproj @@ -2,9 +2,9 @@ netcoreapp3.0 - IISBackwardsCompatibility.FunctionalTests + IISNewHandler.FunctionalTests True - true + true @@ -16,9 +16,6 @@ - - False - False @@ -39,11 +36,4 @@ - - - - <_SourceItemsToCopyToOutputDirectory Remove="@(SourceItemsToRemove)" /> - - - diff --git a/src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/BackwardsCompatibilityTests.cs b/src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/NewHandlerTests.cs similarity index 80% rename from src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/BackwardsCompatibilityTests.cs rename to src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/NewHandlerTests.cs index 1aa826c128..ba2c2c7b4e 100644 --- a/src/Servers/IIS/IIS/test/IIS.BackwardsCompatibility.FunctionalTests/BackwardsCompatibilityTests.cs +++ b/src/Servers/IIS/IIS/test/IIS.NewHandler.FunctionalTests/NewHandlerTests.cs @@ -10,17 +10,17 @@ using Xunit.Sdk; namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests { [Collection(IISTestSiteCollection.Name)] - public class BackwardsCompatibilityTests : FixtureLoggedTest + public class NewHandlerTests : FixtureLoggedTest { private readonly IISTestSiteFixture _fixture; - public BackwardsCompatibilityTests(IISTestSiteFixture fixture) : base(fixture) + public NewHandlerTests(IISTestSiteFixture fixture) : base(fixture) { _fixture = fixture; } [ConditionalFact] - public async Task CheckBackwardsCompatibilityIsUsed() + public async Task CheckNewHandlerIsUsed() { var response = await _fixture.Client.GetAsync("/HelloWorld"); @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests foreach (ProcessModule handle in handles) { - if (handle.ModuleName == "aspnetcorev2.dll") + if (handle.ModuleName == "aspnetcorev2.dll" || handle.ModuleName == "aspnetcorev2_outofprocess.dll") { Assert.Equal("12.2.18316.0", handle.FileVersionInfo.FileVersion); return; diff --git a/src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/DeployerSelector.cs b/src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/DeployerSelector.cs similarity index 88% rename from src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/DeployerSelector.cs rename to src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/DeployerSelector.cs index c53da1c67f..a4f985b16d 100644 --- a/src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/DeployerSelector.cs +++ b/src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/DeployerSelector.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests public static class DeployerSelector { public static ServerType ServerType => ServerType.IIS; - public static bool IsForwardsCompatibilityTest => true; + public static bool IsNewShimTest => true; public static bool HasNewShim => true; public static bool HasNewHandler => false; } diff --git a/src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/ForwardsCompatibilityTests.cs b/src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/ForwardsCompatibilityTests.cs similarity index 84% rename from src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/ForwardsCompatibilityTests.cs rename to src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/ForwardsCompatibilityTests.cs index fdb3aef561..0b18a40f9c 100644 --- a/src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/ForwardsCompatibilityTests.cs +++ b/src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/ForwardsCompatibilityTests.cs @@ -10,17 +10,17 @@ using Xunit.Sdk; namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests { [Collection(IISTestSiteCollection.Name)] - public class ForwardsCompatibilityTests : FixtureLoggedTest + public class NewShimTests : FixtureLoggedTest { private readonly IISTestSiteFixture _fixture; - public ForwardsCompatibilityTests(IISTestSiteFixture fixture) : base(fixture) + public NewShimTests(IISTestSiteFixture fixture) : base(fixture) { _fixture = fixture; } [ConditionalFact] - public async Task CheckForwardsCompatibilityIsUsed() + public async Task CheckNewShimIsUsed() { var response = await _fixture.Client.GetAsync("/HelloWorld"); var handles = _fixture.DeploymentResult.HostProcess.Modules; diff --git a/src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/IIS.ForwardsCompatibility.FunctionalTests.csproj b/src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/IIS.NewShim.FunctionalTests.csproj similarity index 77% rename from src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/IIS.ForwardsCompatibility.FunctionalTests.csproj rename to src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/IIS.NewShim.FunctionalTests.csproj index e8e19b55af..c79cd88ed3 100644 --- a/src/Servers/IIS/IIS/test/IIS.ForwardsCompatibility.FunctionalTests/IIS.ForwardsCompatibility.FunctionalTests.csproj +++ b/src/Servers/IIS/IIS/test/IIS.NewShim.FunctionalTests/IIS.NewShim.FunctionalTests.csproj @@ -2,9 +2,9 @@ netcoreapp3.0 - IISForwardsCompatibility.FunctionalTests + IISNewShim.FunctionalTests True - true + true @@ -13,7 +13,7 @@ - + False diff --git a/src/Servers/IIS/IIS/test/IIS.Tests/MaxRequestBodySizeTests.cs b/src/Servers/IIS/IIS/test/IIS.Tests/MaxRequestBodySizeTests.cs index 1b34f9a371..2408a8efa2 100644 --- a/src/Servers/IIS/IIS/test/IIS.Tests/MaxRequestBodySizeTests.cs +++ b/src/Servers/IIS/IIS/test/IIS.Tests/MaxRequestBodySizeTests.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.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http.Features; diff --git a/src/Servers/IIS/IIS/test/IISExpress.FunctionalTests/DeployerSelector.cs b/src/Servers/IIS/IIS/test/IISExpress.FunctionalTests/DeployerSelector.cs index 4150eea6bc..f9466c5aae 100644 --- a/src/Servers/IIS/IIS/test/IISExpress.FunctionalTests/DeployerSelector.cs +++ b/src/Servers/IIS/IIS/test/IISExpress.FunctionalTests/DeployerSelector.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests public static class DeployerSelector { public static ServerType ServerType => ServerType.IISExpress; - public static bool IsForwardsCompatibilityTest => false; + public static bool IsNewShimTest => false; public static bool HasNewShim => true; public static bool HasNewHandler => true; } diff --git a/src/Servers/IIS/IIS/test/testassets/InProcessForwardsCompatWebSite/InProcessForwardsCompatWebSite.csproj b/src/Servers/IIS/IIS/test/testassets/InProcessNewShimWebSite/InProcessNewShimWebSite.csproj similarity index 95% rename from src/Servers/IIS/IIS/test/testassets/InProcessForwardsCompatWebSite/InProcessForwardsCompatWebSite.csproj rename to src/Servers/IIS/IIS/test/testassets/InProcessNewShimWebSite/InProcessNewShimWebSite.csproj index 341df1f26b..69852cbf81 100644 --- a/src/Servers/IIS/IIS/test/testassets/InProcessForwardsCompatWebSite/InProcessForwardsCompatWebSite.csproj +++ b/src/Servers/IIS/IIS/test/testassets/InProcessNewShimWebSite/InProcessNewShimWebSite.csproj @@ -5,7 +5,7 @@ netcoreapp3.0 InProcessWebSite - InProcessForwardsCompatWebSite + InProcessNewShimWebSite FORWARDCOMPAT diff --git a/src/Servers/IIS/IISIntegration.sln b/src/Servers/IIS/IISIntegration.sln index 1e41537e31..1d01090d51 100644 --- a/src/Servers/IIS/IISIntegration.sln +++ b/src/Servers/IIS/IISIntegration.sln @@ -63,9 +63,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IIS.Tests", "IIS\test\IIS.T EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.Tests", "IIS\test\Common.Tests\Common.Tests.csproj", "{D17B7B35-5361-4A50-B499-E03E5C3CC095}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IIS.BackwardsCompatibility.FunctionalTests", "IIS\test\IIS.BackwardsCompatibility.FunctionalTests\IIS.BackwardsCompatibility.FunctionalTests.csproj", "{582B07BC-73F4-4689-8557-B039298BD82C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IIS.NewHandler.FunctionalTests", "IIS\test\IIS.NewHandler.FunctionalTests\IIS.NewHandler.FunctionalTests.csproj", "{582B07BC-73F4-4689-8557-B039298BD82C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IIS.ForwardsCompatibility.FunctionalTests", "IIS\test\IIS.ForwardsCompatibility.FunctionalTests\IIS.ForwardsCompatibility.FunctionalTests.csproj", "{D1EA5D99-28FD-4197-81DE-17098846B38B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IIS.NewShim.FunctionalTests", "IIS\test\IIS.NewShim.FunctionalTests\IIS.NewShim.FunctionalTests.csproj", "{D1EA5D99-28FD-4197-81DE-17098846B38B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestTasks", "IIS\test\testassets\TestTasks\TestTasks.csproj", "{2DD1269D-131C-4531-BB0D-7BE0EF8E56D0}" EndProject diff --git a/src/Servers/IIS/IntegrationTesting.IIS/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS.csproj b/src/Servers/IIS/IntegrationTesting.IIS/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS.csproj index efd3c18b4c..cbfb23b75b 100644 --- a/src/Servers/IIS/IntegrationTesting.IIS/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS.csproj +++ b/src/Servers/IIS/IntegrationTesting.IIS/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS.csproj @@ -27,7 +27,7 @@ Condition="!Exists('$(AspNetCoreModuleV2ShimDll)') OR !Exists('$(AspNetCoreModuleV2OutOfProcessHandlerDll)')" /> - + diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/HPack/IntegerEncoder.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/HPack/IntegerEncoder.cs index 63da553db2..15beb845f7 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/HPack/IntegerEncoder.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/HPack/IntegerEncoder.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; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.HPack { @@ -9,6 +10,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.HPack { public static bool Encode(int i, int n, Span buffer, out int length) { + Debug.Assert(i >= 0); + Debug.Assert(n >= 1 && n <= 8); + var j = 0; length = 0; @@ -37,7 +41,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.HPack { buffer[j++] = (byte)(i % 128 + 128); - if (j > buffer.Length) + if (j >= buffer.Length) { return false; } diff --git a/src/Servers/Kestrel/Core/test/HPackIntegerTests.cs b/src/Servers/Kestrel/Core/test/HPackIntegerTests.cs index 06cd800a7f..4448463dd4 100644 --- a/src/Servers/Kestrel/Core/test/HPackIntegerTests.cs +++ b/src/Servers/Kestrel/Core/test/HPackIntegerTests.cs @@ -1,6 +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.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.HPack; using Xunit; @@ -35,5 +37,55 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } } } + + [Theory] + [MemberData(nameof(IntegerCodecSamples))] + public void EncodeSamples(int value, int bits, byte[] expectedResult) + { + Span actualResult = new byte[64]; + bool success = IntegerEncoder.Encode(value, bits, actualResult, out int bytesWritten); + + Assert.True(success); + Assert.Equal(expectedResult.Length, bytesWritten); + Assert.True(actualResult.Slice(0, bytesWritten).SequenceEqual(expectedResult)); + } + + [Theory] + [MemberData(nameof(IntegerCodecSamples))] + public void EncodeSamplesWithShortBuffer(int value, int bits, byte[] expectedResult) + { + Span actualResult = new byte[expectedResult.Length - 1]; + bool success = IntegerEncoder.Encode(value, bits, actualResult, out int bytesWritten); + + Assert.False(success); + } + + [Theory] + [MemberData(nameof(IntegerCodecSamples))] + public void DecodeSamples(int expectedResult, int bits, byte[] encoded) + { + var integerDecoder = new IntegerDecoder(); + + bool finished = integerDecoder.BeginTryDecode(encoded[0], bits, out int actualResult); + + int i = 1; + for (; !finished && i < encoded.Length; ++i) + { + finished = integerDecoder.TryDecode(encoded[i], out actualResult); + } + + Assert.True(finished); + Assert.Equal(encoded.Length, i); + + Assert.Equal(expectedResult, actualResult); + } + + // integer, prefix length, encoded + public static IEnumerable IntegerCodecSamples() + { + yield return new object[] { 10, 5, new byte[] { 0x0A } }; + yield return new object[] { 1337, 5, new byte[] { 0x1F, 0x9A, 0x0A } }; + yield return new object[] { 42, 8, new byte[] { 0x2A } }; + } } } diff --git a/src/Shared/CertificateGeneration/CertificateManager.cs b/src/Shared/CertificateGeneration/CertificateManager.cs index 78ea93398c..14d26abbcd 100644 --- a/src/Shared/CertificateGeneration/CertificateManager.cs +++ b/src/Shared/CertificateGeneration/CertificateManager.cs @@ -42,6 +42,10 @@ namespace Microsoft.AspNetCore.Certificates.Generation private static readonly string MacOSTrustCertificateCommandLineArguments = "security add-trusted-cert -d -r trustRoot -k " + MacOSSystemKeyChain + " "; private const int UserCancelledErrorCode = 1223; + // Setting to 0 means we don't append the version byte, + // which is what all machines currently have. + public int AspNetHttpsCertificateVersion { get; set; } = 1; + public IList ListCertificates( CertificatePurpose purpose, StoreName storeName, @@ -83,7 +87,8 @@ namespace Microsoft.AspNetCore.Certificates.Generation var validCertificates = matchingCertificates .Where(c => c.NotBefore <= now && now <= c.NotAfter && - (!requireExportable || !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || IsExportable(c))) + (!requireExportable || !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || IsExportable(c)) + && MatchesVersion(c)) .ToArray(); var invalidCertificates = matchingCertificates.Except(validCertificates); @@ -117,6 +122,25 @@ namespace Microsoft.AspNetCore.Certificates.Generation bool HasOid(X509Certificate2 certificate, string oid) => certificate.Extensions.OfType() .Any(e => string.Equals(oid, e.Oid.Value, StringComparison.Ordinal)); + + bool MatchesVersion(X509Certificate2 c) + { + var byteArray = c.Extensions.OfType() + .Where(e => string.Equals(AspNetHttpsOid, e.Oid.Value, StringComparison.Ordinal)) + .Single() + .RawData; + + if ((byteArray.Length == AspNetHttpsOidFriendlyName.Length && byteArray[0] == (byte)'A') || byteArray.Length == 0) + { + // No Version set, default to 0 + return 0 >= AspNetHttpsCertificateVersion; + } + else + { + // Version is in the only byte of the byte array. + return byteArray[0] >= AspNetHttpsCertificateVersion; + } + } #if !XPLAT bool IsExportable(X509Certificate2 c) => ((c.GetRSAPrivateKey() is RSACryptoServiceProvider rsaPrivateKey && @@ -171,10 +195,22 @@ namespace Microsoft.AspNetCore.Certificates.Generation pathLengthConstraint: 0, critical: true); + byte[] bytePayload; + + if (AspNetHttpsCertificateVersion != 0) + { + bytePayload = new byte[1]; + bytePayload[0] = (byte)AspNetHttpsCertificateVersion; + } + else + { + bytePayload = Encoding.ASCII.GetBytes(AspNetHttpsOidFriendlyName); + } + var aspNetHttpsExtension = new X509Extension( new AsnEncodedData( new Oid(AspNetHttpsOid, AspNetHttpsOidFriendlyName), - Encoding.ASCII.GetBytes(AspNetHttpsOidFriendlyName)), + bytePayload), critical: false); extensions.Add(basicConstraints); @@ -633,7 +669,7 @@ namespace Microsoft.AspNetCore.Certificates.Generation } } - public EnsureCertificateResult EnsureAspNetCoreHttpsDevelopmentCertificate( + public DetailedEnsureCertificateResult EnsureAspNetCoreHttpsDevelopmentCertificate( DateTimeOffset notBefore, DateTimeOffset notAfter, string path = null, @@ -645,109 +681,7 @@ namespace Microsoft.AspNetCore.Certificates.Generation return EnsureValidCertificateExists(notBefore, notAfter, CertificatePurpose.HTTPS, path, trust, includePrivateKey, password, subject); } - public EnsureCertificateResult EnsureValidCertificateExists( - DateTimeOffset notBefore, - DateTimeOffset notAfter, - CertificatePurpose purpose, - string path = null, - bool trust = false, - bool includePrivateKey = false, - string password = null, - string subjectOverride = null) - { - if (purpose == CertificatePurpose.All) - { - throw new ArgumentException("The certificate must have a specific purpose."); - } - - var certificates = ListCertificates(purpose, StoreName.My, StoreLocation.CurrentUser, isValid: true).Concat( - ListCertificates(purpose, StoreName.My, StoreLocation.LocalMachine, isValid: true)); - - certificates = subjectOverride == null ? certificates : certificates.Where(c => c.Subject == subjectOverride); - - var result = EnsureCertificateResult.Succeeded; - - X509Certificate2 certificate = null; - if (certificates.Count() > 0) - { - certificate = certificates.FirstOrDefault(); - result = EnsureCertificateResult.ValidCertificatePresent; - } - else - { - try - { - switch (purpose) - { - case CertificatePurpose.All: - throw new InvalidOperationException("The certificate must have a specific purpose."); - case CertificatePurpose.HTTPS: - certificate = CreateAspNetCoreHttpsDevelopmentCertificate(notBefore, notAfter, subjectOverride); - break; - default: - throw new InvalidOperationException("The certificate must have a purpose."); - } - } - catch - { - return EnsureCertificateResult.ErrorCreatingTheCertificate; - } - - try - { - certificate = SaveCertificateInStore(certificate, StoreName.My, StoreLocation.CurrentUser); - } - catch - { - return EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore; - } - } - if (path != null) - { - try - { - ExportCertificate(certificate, path, includePrivateKey, password); - } - catch - { - return EnsureCertificateResult.ErrorExportingTheCertificate; - } - } - - if ((RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) && trust) - { - try - { - TrustCertificate(certificate); - } - catch (UserCancelledTrustException) - { - return EnsureCertificateResult.UserCancelledTrustStep; - } - catch - { - return EnsureCertificateResult.FailedToTrustTheCertificate; - } - } - - return result; - } - - // This is just to avoid breaking changes across repos. - // Will be renamed back to EnsureAspNetCoreHttpsDevelopmentCertificate once updates are made elsewhere. - public DetailedEnsureCertificateResult EnsureAspNetCoreHttpsDevelopmentCertificate2( - DateTimeOffset notBefore, - DateTimeOffset notAfter, - string path = null, - bool trust = false, - bool includePrivateKey = false, - string password = null, - string subject = LocalhostHttpsDistinguishedName) - { - return EnsureValidCertificateExists2(notBefore, notAfter, CertificatePurpose.HTTPS, path, trust, includePrivateKey, password, subject); - } - - public DetailedEnsureCertificateResult EnsureValidCertificateExists2( + public DetailedEnsureCertificateResult EnsureValidCertificateExists( DateTimeOffset notBefore, DateTimeOffset notAfter, CertificatePurpose purpose, diff --git a/src/Shared/PropertyActivator/PropertyActivator.cs b/src/Shared/PropertyActivator/PropertyActivator.cs index 925f6a76ae..b1d730efaf 100644 --- a/src/Shared/PropertyActivator/PropertyActivator.cs +++ b/src/Shared/PropertyActivator/PropertyActivator.cs @@ -15,19 +15,9 @@ namespace Microsoft.Extensions.Internal public PropertyActivator( PropertyInfo propertyInfo, Func valueAccessor) - { - if (propertyInfo == null) - { - throw new ArgumentNullException(nameof(propertyInfo)); - } - - if (valueAccessor == null) - { - throw new ArgumentNullException(nameof(valueAccessor)); - } - - PropertyInfo = propertyInfo; - _valueAccessor = valueAccessor; + { + PropertyInfo = propertyInfo ?? throw new ArgumentNullException(nameof(propertyInfo)); + _valueAccessor = valueAccessor ?? throw new ArgumentNullException(nameof(valueAccessor)); _fastPropertySetter = PropertyHelper.MakeFastPropertySetter(propertyInfo); } @@ -107,4 +97,4 @@ namespace Microsoft.Extensions.Internal return properties.Select(createActivateInfo).ToArray(); } } -} \ No newline at end of file +} diff --git a/src/Shared/PropertyHelper/PropertyHelper.cs b/src/Shared/PropertyHelper/PropertyHelper.cs index f3641e03dc..3349833264 100644 --- a/src/Shared/PropertyHelper/PropertyHelper.cs +++ b/src/Shared/PropertyHelper/PropertyHelper.cs @@ -51,13 +51,8 @@ namespace Microsoft.Extensions.Internal /// This constructor does not cache the helper. For caching, use . /// public PropertyHelper(PropertyInfo property) - { - if (property == null) - { - throw new ArgumentNullException(nameof(property)); - } - - Property = property; + { + Property = property ?? throw new ArgumentNullException(nameof(property)); Name = property.Name; } diff --git a/src/SignalR/clients/ts/signalr/src/DefaultReconnectPolicy.ts b/src/SignalR/clients/ts/signalr/src/DefaultReconnectPolicy.ts index 1a5ae81cde..34658c5cbc 100644 --- a/src/SignalR/clients/ts/signalr/src/DefaultReconnectPolicy.ts +++ b/src/SignalR/clients/ts/signalr/src/DefaultReconnectPolicy.ts @@ -1,20 +1,20 @@ // 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. -import { IReconnectPolicy } from "./IReconnectPolicy"; +import { IRetryPolicy, RetryContext } from "./IRetryPolicy"; // 0, 2, 10, 30 second delays before reconnect attempts. const DEFAULT_RETRY_DELAYS_IN_MILLISECONDS = [0, 2000, 10000, 30000, null]; /** @private */ -export class DefaultReconnectPolicy implements IReconnectPolicy { +export class DefaultReconnectPolicy implements IRetryPolicy { private readonly retryDelays: Array; constructor(retryDelays?: number[]) { this.retryDelays = retryDelays !== undefined ? [...retryDelays, null] : DEFAULT_RETRY_DELAYS_IN_MILLISECONDS; } - public nextRetryDelayInMilliseconds(previousRetryCount: number): number | null { - return this.retryDelays[previousRetryCount]; + public nextRetryDelayInMilliseconds(retryContext: RetryContext): number | null { + return this.retryDelays[retryContext.previousRetryCount]; } } diff --git a/src/SignalR/clients/ts/signalr/src/HubConnection.ts b/src/SignalR/clients/ts/signalr/src/HubConnection.ts index 1247c35797..f604fb09b2 100644 --- a/src/SignalR/clients/ts/signalr/src/HubConnection.ts +++ b/src/SignalR/clients/ts/signalr/src/HubConnection.ts @@ -5,7 +5,7 @@ import { HandshakeProtocol, HandshakeRequestMessage, HandshakeResponseMessage } import { IConnection } from "./IConnection"; import { CancelInvocationMessage, CompletionMessage, IHubProtocol, InvocationMessage, MessageType, StreamInvocationMessage, StreamItemMessage } from "./IHubProtocol"; import { ILogger, LogLevel } from "./ILogger"; -import { IReconnectPolicy } from "./IReconnectPolicy"; +import { IRetryPolicy } from "./IRetryPolicy"; import { IStreamResult } from "./Stream"; import { Subject } from "./Subject"; import { Arg } from "./Utils"; @@ -32,7 +32,7 @@ export class HubConnection { private readonly cachedPingMessage: string | ArrayBuffer; private readonly connection: IConnection; private readonly logger: ILogger; - private readonly reconnectPolicy?: IReconnectPolicy; + private readonly reconnectPolicy?: IRetryPolicy; private protocol: IHubProtocol; private handshakeProtocol: HandshakeProtocol; private callbacks: { [invocationId: string]: (invocationEvent: StreamItemMessage | CompletionMessage | null, error?: Error) => void }; @@ -81,11 +81,11 @@ export class HubConnection { // create method that can be used by HubConnectionBuilder. An "internal" constructor would just // be stripped away and the '.d.ts' file would have no constructor, which is interpreted as a // public parameter-less constructor. - public static create(connection: IConnection, logger: ILogger, protocol: IHubProtocol, reconnectPolicy?: IReconnectPolicy): HubConnection { + public static create(connection: IConnection, logger: ILogger, protocol: IHubProtocol, reconnectPolicy?: IRetryPolicy): HubConnection { return new HubConnection(connection, logger, protocol, reconnectPolicy); } - private constructor(connection: IConnection, logger: ILogger, protocol: IHubProtocol, reconnectPolicy?: IReconnectPolicy) { + private constructor(connection: IConnection, logger: ILogger, protocol: IHubProtocol, reconnectPolicy?: IRetryPolicy) { Arg.isRequired(connection, "connection"); Arg.isRequired(logger, "logger"); Arg.isRequired(protocol, "protocol"); @@ -666,11 +666,12 @@ export class HubConnection { private async reconnect(error?: Error) { const reconnectStartTime = Date.now(); let previousReconnectAttempts = 0; + let retryError = error !== undefined ? error : new Error("Attempting to reconnect due to a unknown error."); - let nextRetryDelay = this.getNextRetryDelay(previousReconnectAttempts++, 0); + let nextRetryDelay = this.getNextRetryDelay(previousReconnectAttempts++, 0, retryError); if (nextRetryDelay === null) { - this.logger.log(LogLevel.Debug, "Connection not reconnecting because the IReconnectPolicy returned null on the first reconnect attempt."); + this.logger.log(LogLevel.Debug, "Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."); this.completeClose(error); return; } @@ -732,9 +733,10 @@ export class HubConnection { this.logger.log(LogLevel.Debug, "Connection left the reconnecting state during reconnect attempt. Done reconnecting."); return; } - } - nextRetryDelay = this.getNextRetryDelay(previousReconnectAttempts++, Date.now() - reconnectStartTime); + retryError = e instanceof Error ? e : new Error(e.toString()); + nextRetryDelay = this.getNextRetryDelay(previousReconnectAttempts++, Date.now() - reconnectStartTime, retryError); + } } this.logger.log(LogLevel.Information, `Reconnect retries have been exhausted after ${Date.now() - reconnectStartTime} ms and ${previousReconnectAttempts} failed attempts. Connection disconnecting.`); @@ -742,11 +744,15 @@ export class HubConnection { this.completeClose(); } - private getNextRetryDelay(previousRetryCount: number, elapsedMilliseconds: number) { + private getNextRetryDelay(previousRetryCount: number, elapsedMilliseconds: number, retryReason: Error) { try { - return this.reconnectPolicy!.nextRetryDelayInMilliseconds(previousRetryCount, elapsedMilliseconds); + return this.reconnectPolicy!.nextRetryDelayInMilliseconds({ + elapsedMilliseconds, + previousRetryCount, + retryReason, + }); } catch (e) { - this.logger.log(LogLevel.Error, `IReconnectPolicy.nextRetryDelayInMilliseconds(${previousRetryCount}, ${elapsedMilliseconds}) threw error '${e}'.`); + this.logger.log(LogLevel.Error, `IRetryPolicy.nextRetryDelayInMilliseconds(${previousRetryCount}, ${elapsedMilliseconds}) threw error '${e}'.`); return null; } } diff --git a/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts b/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts index c9ae4e15d9..06a7426791 100644 --- a/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts +++ b/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts @@ -7,7 +7,7 @@ import { HubConnection } from "./HubConnection"; import { IHttpConnectionOptions } from "./IHttpConnectionOptions"; import { IHubProtocol } from "./IHubProtocol"; import { ILogger, LogLevel } from "./ILogger"; -import { IReconnectPolicy } from "./IReconnectPolicy"; +import { IRetryPolicy } from "./IRetryPolicy"; import { HttpTransportType } from "./ITransport"; import { JsonHubProtocol } from "./JsonHubProtocol"; import { NullLogger } from "./Loggers"; @@ -51,7 +51,7 @@ export class HubConnectionBuilder { /** If defined, this indicates the client should automatically attempt to reconnect if the connection is lost. */ /** @internal */ - public reconnectPolicy?: IReconnectPolicy; + public reconnectPolicy?: IRetryPolicy; /** Configures console logging for the {@link @aspnet/signalr.HubConnection}. * @@ -164,10 +164,10 @@ export class HubConnectionBuilder { /** Configures the {@link @aspnet/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost. * - * @param {IReconnectPolicy} reconnectPolicy An {@link @aspnet/signalR.IReconnectPolicy} that controls the timing and number of reconnect attempts. + * @param {IRetryPolicy} reconnectPolicy An {@link @aspnet/signalR.IRetryPolicy} that controls the timing and number of reconnect attempts. */ - public withAutomaticReconnect(reconnectPolicy: IReconnectPolicy): HubConnectionBuilder; - public withAutomaticReconnect(retryDelaysOrReconnectPolicy?: number[] | IReconnectPolicy): HubConnectionBuilder { + public withAutomaticReconnect(reconnectPolicy: IRetryPolicy): HubConnectionBuilder; + public withAutomaticReconnect(retryDelaysOrReconnectPolicy?: number[] | IRetryPolicy): HubConnectionBuilder { if (this.reconnectPolicy) { throw new Error("A reconnectPolicy has already been set."); } diff --git a/src/SignalR/clients/ts/signalr/src/IReconnectPolicy.ts b/src/SignalR/clients/ts/signalr/src/IReconnectPolicy.ts deleted file mode 100644 index 7f316aa2ca..0000000000 --- a/src/SignalR/clients/ts/signalr/src/IReconnectPolicy.ts +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -/** An abstraction that controls when the client attempts to reconnect and how many times it does so. */ -export interface IReconnectPolicy { - /** Called after the transport loses the connection. - * - * @param {number} previousRetryCount The number of consecutive failed reconnect attempts so far. - * - * @param {number} elapsedMilliseconds The amount of time in milliseconds spent reconnecting so far. - * - * @returns {number | null} The amount of time in milliseconds to wait before the next reconnect attempt. `null` tells the client to stop retrying and close. - */ - nextRetryDelayInMilliseconds(previousRetryCount: number, elapsedMilliseconds: number): number | null; -} diff --git a/src/SignalR/clients/ts/signalr/src/IRetryPolicy.ts b/src/SignalR/clients/ts/signalr/src/IRetryPolicy.ts new file mode 100644 index 0000000000..fb615a0033 --- /dev/null +++ b/src/SignalR/clients/ts/signalr/src/IRetryPolicy.ts @@ -0,0 +1,30 @@ +// 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. + +/** An abstraction that controls when the client attempts to reconnect and how many times it does so. */ +export interface IRetryPolicy { + /** Called after the transport loses the connection. + * + * @param {RetryContext} retryContext Details related to the retry event to help determine how long to wait for the next retry. + * + * @returns {number | null} The amount of time in milliseconds to wait before the next retry. `null` tells the client to stop retrying. + */ + nextRetryDelayInMilliseconds(retryContext: RetryContext): number | null; +} + +export interface RetryContext { + /** + * The number of consecutive failed tries so far. + */ + readonly previousRetryCount: number; + + /** + * The amount of time in milliseconds spent retrying so far. + */ + readonly elapsedMilliseconds: number; + + /** + * The error that forced the upcoming retry. + */ + readonly retryReason: Error; +} diff --git a/src/SignalR/clients/ts/signalr/src/index.ts b/src/SignalR/clients/ts/signalr/src/index.ts index 98cb0106d6..dc2086c661 100644 --- a/src/SignalR/clients/ts/signalr/src/index.ts +++ b/src/SignalR/clients/ts/signalr/src/index.ts @@ -21,4 +21,4 @@ export { IStreamSubscriber, IStreamResult, ISubscription } from "./Stream"; export { NullLogger } from "./Loggers"; export { JsonHubProtocol } from "./JsonHubProtocol"; export { Subject } from "./Subject"; -export { IReconnectPolicy } from "./IReconnectPolicy"; +export { IRetryPolicy, RetryContext } from "./IRetryPolicy"; diff --git a/src/SignalR/clients/ts/signalr/tests/HubConnection.Reconnect.test.ts b/src/SignalR/clients/ts/signalr/tests/HubConnection.Reconnect.test.ts index 9b1d3b34e7..542a5217d9 100644 --- a/src/SignalR/clients/ts/signalr/tests/HubConnection.Reconnect.test.ts +++ b/src/SignalR/clients/ts/signalr/tests/HubConnection.Reconnect.test.ts @@ -3,6 +3,7 @@ import { DefaultReconnectPolicy } from "../src/DefaultReconnectPolicy"; import { HubConnection, HubConnectionState } from "../src/HubConnection"; +import { RetryContext } from "../src/IRetryPolicy"; import { JsonHubProtocol } from "../src/JsonHubProtocol"; import { VerifyLogger } from "./Common"; @@ -46,15 +47,17 @@ describe("auto reconnect", () => { let lastRetryCount = -1; let lastElapsedMs = -1; + let retryReason = null; let onreconnectingCount = 0; let onreconnectedCount = 0; let closeCount = 0; const connection = new TestConnection(); const hubConnection = HubConnection.create(connection, logger, new JsonHubProtocol(), { - nextRetryDelayInMilliseconds(previousRetryCount: number, elapsedMilliseconds: number) { - lastRetryCount = previousRetryCount; - lastElapsedMs = elapsedMilliseconds; + nextRetryDelayInMilliseconds(retryContext: RetryContext) { + lastRetryCount = retryContext.previousRetryCount; + lastElapsedMs = retryContext.elapsedMilliseconds; + retryReason = retryContext.retryReason; nextRetryDelayCalledPromise.resolve(); return 0; }, @@ -81,8 +84,11 @@ describe("auto reconnect", () => { return promise; }; + const oncloseError = new Error("Connection lost"); + const continueRetryingError = new Error("Reconnect attempt failed"); + // Typically this would be called by the transport - connection.onclose!(new Error("Connection lost")); + connection.onclose!(oncloseError); await nextRetryDelayCalledPromise; nextRetryDelayCalledPromise = new PromiseSource(); @@ -90,17 +96,19 @@ describe("auto reconnect", () => { expect(hubConnection.state).toBe(HubConnectionState.Reconnecting); expect(lastRetryCount).toBe(0); expect(lastElapsedMs).toBe(0); + expect(retryReason).toBe(oncloseError); expect(onreconnectingCount).toBe(1); expect(onreconnectedCount).toBe(0); expect(closeCount).toBe(0); // Make sure the the Promise is "handled" immediately upon rejection or else this test fails. continueRetryingPromise.catch(() => { }); - continueRetryingPromise.reject(new Error("Reconnect attempt failed")); + continueRetryingPromise.reject(continueRetryingError); await nextRetryDelayCalledPromise; expect(lastRetryCount).toBe(1); expect(lastElapsedMs).toBeGreaterThanOrEqual(0); + expect(retryReason).toBe(continueRetryingError); expect(onreconnectingCount).toBe(1); expect(onreconnectedCount).toBe(0); expect(closeCount).toBe(0); @@ -133,18 +141,20 @@ describe("auto reconnect", () => { let lastRetryCount = -1; let lastElapsedMs = -1; + let retryReason = null; let onreconnectingCount = 0; let onreconnectedCount = 0; let closeCount = 0; const connection = new TestConnection(); const hubConnection = HubConnection.create(connection, logger, new JsonHubProtocol(), { - nextRetryDelayInMilliseconds(previousRetryCount: number, elapsedMilliseconds: number) { - lastRetryCount = previousRetryCount; - lastElapsedMs = elapsedMilliseconds; + nextRetryDelayInMilliseconds(retryContext: RetryContext) { + lastRetryCount = retryContext.previousRetryCount; + lastElapsedMs = retryContext.elapsedMilliseconds; + retryReason = retryContext.retryReason; nextRetryDelayCalledPromise.resolve(); - return previousRetryCount === 0 ? 0 : null; + return retryContext.previousRetryCount === 0 ? 0 : null; }, }); @@ -163,12 +173,15 @@ describe("auto reconnect", () => { await hubConnection.start(); + const oncloseError = new Error("Connection lost"); + const startError = new Error("Reconnect attempt failed"); + connection.start = () => { - return Promise.reject("Reconnect attempt failed"); + throw startError; }; // Typically this would be called by the transport - connection.onclose!(new Error("Connection lost")); + connection.onclose!(oncloseError); await nextRetryDelayCalledPromise; nextRetryDelayCalledPromise = new PromiseSource(); @@ -176,6 +189,7 @@ describe("auto reconnect", () => { expect(hubConnection.state).toBe(HubConnectionState.Reconnecting); expect(lastRetryCount).toBe(0); expect(lastElapsedMs).toBe(0); + expect(retryReason).toBe(oncloseError); expect(onreconnectingCount).toBe(1); expect(onreconnectedCount).toBe(0); expect(closeCount).toBe(0); @@ -185,6 +199,7 @@ describe("auto reconnect", () => { expect(hubConnection.state).toBe(HubConnectionState.Disconnected); expect(lastRetryCount).toBe(1); expect(lastElapsedMs).toBeGreaterThanOrEqual(0); + expect(retryReason).toBe(startError); expect(onreconnectingCount).toBe(1); expect(onreconnectedCount).toBe(0); expect(closeCount).toBe(1); @@ -198,15 +213,17 @@ describe("auto reconnect", () => { let lastRetryCount = -1; let lastElapsedMs = -1; + let retryReason = null; let onreconnectingCount = 0; let onreconnectedCount = 0; let closeCount = 0; const connection = new TestConnection(); const hubConnection = HubConnection.create(connection, logger, new JsonHubProtocol(), { - nextRetryDelayInMilliseconds(previousRetryCount: number, elapsedMilliseconds: number) { - lastRetryCount = previousRetryCount; - lastElapsedMs = elapsedMilliseconds; + nextRetryDelayInMilliseconds(retryContext: RetryContext) { + lastRetryCount = retryContext.previousRetryCount; + lastElapsedMs = retryContext.elapsedMilliseconds; + retryReason = retryContext.retryReason; nextRetryDelayCalledPromise.resolve(); return 0; }, @@ -227,8 +244,11 @@ describe("auto reconnect", () => { await hubConnection.start(); + const oncloseError = new Error("Connection lost 1"); + const oncloseError2 = new Error("Connection lost 2"); + // Typically this would be called by the transport - connection.onclose!(new Error("Connection lost")); + connection.onclose!(oncloseError); await nextRetryDelayCalledPromise; nextRetryDelayCalledPromise = new PromiseSource(); @@ -236,6 +256,7 @@ describe("auto reconnect", () => { expect(hubConnection.state).toBe(HubConnectionState.Reconnecting); expect(lastRetryCount).toBe(0); expect(lastElapsedMs).toBe(0); + expect(retryReason).toBe(oncloseError); expect(onreconnectingCount).toBe(1); expect(onreconnectedCount).toBe(0); expect(closeCount).toBe(0); @@ -250,13 +271,14 @@ describe("auto reconnect", () => { expect(onreconnectedCount).toBe(1); expect(closeCount).toBe(0); - connection.onclose!(new Error("Connection lost")); + connection.onclose!(oncloseError2); await nextRetryDelayCalledPromise; expect(hubConnection.state).toBe(HubConnectionState.Reconnecting); expect(lastRetryCount).toBe(0); expect(lastElapsedMs).toBe(0); + expect(retryReason).toBe(oncloseError2); expect(onreconnectingCount).toBe(2); expect(onreconnectedCount).toBe(1); expect(closeCount).toBe(0); @@ -362,6 +384,7 @@ describe("auto reconnect", () => { let nextRetryDelayCalledPromise = new PromiseSource(); let lastRetryCount = 0; + let retryReason = null; let onreconnectingCount = 0; let onreconnectedCount = 0; let closeCount = 0; @@ -369,8 +392,9 @@ describe("auto reconnect", () => { // Disable autoHandshake in TestConnection const connection = new TestConnection(false); const hubConnection = HubConnection.create(connection, logger, new JsonHubProtocol(), { - nextRetryDelayInMilliseconds(previousRetryCount: number) { - lastRetryCount = previousRetryCount; + nextRetryDelayInMilliseconds(retryContext: RetryContext) { + lastRetryCount = retryContext.previousRetryCount; + retryReason = retryContext.retryReason; nextRetryDelayCalledPromise.resolve(); return 0; }, @@ -400,14 +424,18 @@ describe("auto reconnect", () => { return Promise.resolve(); }; + const oncloseError = new Error("Connection lost 1"); + const oncloseError2 = new Error("Connection lost 2"); + // Typically this would be called by the transport - connection.onclose!(new Error("Connection lost")); + connection.onclose!(oncloseError); await nextRetryDelayCalledPromise; nextRetryDelayCalledPromise = new PromiseSource(); expect(hubConnection.state).toBe(HubConnectionState.Reconnecting); expect(lastRetryCount).toBe(0); + expect(retryReason).toBe(oncloseError); expect(onreconnectingCount).toBe(1); expect(onreconnectedCount).toBe(0); expect(closeCount).toBe(0); @@ -416,12 +444,13 @@ describe("auto reconnect", () => { replacedStartCalledPromise = new PromiseSource(); // Fail underlying connection during reconnect during handshake - connection.onclose!(new Error("Connection lost")); + connection.onclose!(oncloseError2); await nextRetryDelayCalledPromise; expect(hubConnection.state).toBe(HubConnectionState.Reconnecting); expect(lastRetryCount).toBe(1); + expect(retryReason).toBe(oncloseError2); expect(onreconnectingCount).toBe(1); expect(onreconnectedCount).toBe(0); expect(closeCount).toBe(0); @@ -461,8 +490,8 @@ describe("auto reconnect", () => { // Disable autoHandshake in TestConnection const connection = new TestConnection(false); const hubConnection = HubConnection.create(connection, logger, new JsonHubProtocol(), { - nextRetryDelayInMilliseconds(previousRetryCount: number) { - lastRetryCount = previousRetryCount; + nextRetryDelayInMilliseconds(retryContext: RetryContext) { + lastRetryCount = retryContext.previousRetryCount; nextRetryDelayCalledPromise.resolve(); return 0; }, diff --git a/src/SignalR/clients/ts/signalr/tests/HubConnectionBuilder.test.ts b/src/SignalR/clients/ts/signalr/tests/HubConnectionBuilder.test.ts index c0a331e558..4aaa70a0d8 100644 --- a/src/SignalR/clients/ts/signalr/tests/HubConnectionBuilder.test.ts +++ b/src/SignalR/clients/ts/signalr/tests/HubConnectionBuilder.test.ts @@ -322,7 +322,13 @@ describe("HubConnectionBuilder", () => { let retryCount = 0; for (const delay of DEFAULT_RETRY_DELAYS_IN_MILLISECONDS) { - expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryCount++, 0)).toBe(delay); + const retryContext = { + previousRetryCount: retryCount++, + elapsedMilliseconds: 0, + retryReason: new Error(), + }; + + expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryContext)).toBe(delay); } }); @@ -333,23 +339,47 @@ describe("HubConnectionBuilder", () => { let retryCount = 0; for (const delay of customRetryDelays) { - expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryCount++, 0)).toBe(delay); + const retryContext = { + previousRetryCount: retryCount++, + elapsedMilliseconds: 0, + retryReason: new Error(), + }; + + expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryContext)).toBe(delay); } - expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryCount, 0)).toBe(null); + const retryContextFinal = { + previousRetryCount: retryCount++, + elapsedMilliseconds: 0, + retryReason: new Error(), + }; + + expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryContextFinal)).toBe(null); }); - it("withAutomaticReconnect uses a custom IReconnectPolicy when provided", () => { + it("withAutomaticReconnect uses a custom IRetryPolicy when provided", () => { const customRetryDelays = [127, 0, 0, 1]; const builder = new HubConnectionBuilder() .withAutomaticReconnect(new DefaultReconnectPolicy(customRetryDelays)); let retryCount = 0; for (const delay of customRetryDelays) { - expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryCount++, 0)).toBe(delay); + const retryContext = { + previousRetryCount: retryCount++, + elapsedMilliseconds: 0, + retryReason: new Error(), + }; + + expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryContext)).toBe(delay); } - expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryCount, 0)).toBe(null); + const retryContextFinal = { + previousRetryCount: retryCount++, + elapsedMilliseconds: 0, + retryReason: new Error(), + }; + + expect(builder.reconnectPolicy!.nextRetryDelayInMilliseconds(retryContextFinal)).toBe(null); }); }); diff --git a/src/SignalR/common/Protocols.Json/src/Protocol/JsonHubProtocol.cs b/src/SignalR/common/Protocols.Json/src/Protocol/JsonHubProtocol.cs index a943ab736a..21a2ecb743 100644 --- a/src/SignalR/common/Protocols.Json/src/Protocol/JsonHubProtocol.cs +++ b/src/SignalR/common/Protocols.Json/src/Protocol/JsonHubProtocol.cs @@ -762,7 +762,7 @@ namespace Microsoft.AspNetCore.SignalR.Protocol options.IgnoreNullValues = false; options.IgnoreReadOnlyProperties = false; options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - options.PropertyNameCaseInsensitive = false; + options.PropertyNameCaseInsensitive = true; options.MaxDepth = 64; options.DictionaryKeyPolicy = null; options.DefaultBufferSize = 16 * 1024; diff --git a/src/SignalR/common/Protocols.MessagePack/ref/Microsoft.AspNetCore.SignalR.Protocols.MessagePack.netstandard2.0.cs b/src/SignalR/common/Protocols.MessagePack/ref/Microsoft.AspNetCore.SignalR.Protocols.MessagePack.netstandard2.0.cs index ec222f2318..70f7ce9d02 100644 --- a/src/SignalR/common/Protocols.MessagePack/ref/Microsoft.AspNetCore.SignalR.Protocols.MessagePack.netstandard2.0.cs +++ b/src/SignalR/common/Protocols.MessagePack/ref/Microsoft.AspNetCore.SignalR.Protocols.MessagePack.netstandard2.0.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.SignalR public partial class MessagePackHubProtocolOptions { public MessagePackHubProtocolOptions() { } - public System.Collections.Generic.IList FormatterResolvers { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public System.Collections.Generic.IList FormatterResolvers { get { throw null; } set { } } } } namespace Microsoft.AspNetCore.SignalR.Protocol diff --git a/src/SignalR/common/Protocols.MessagePack/src/MessagePackHubProtocolOptions.cs b/src/SignalR/common/Protocols.MessagePack/src/MessagePackHubProtocolOptions.cs index 95ddfe6a9b..85025b6444 100644 --- a/src/SignalR/common/Protocols.MessagePack/src/MessagePackHubProtocolOptions.cs +++ b/src/SignalR/common/Protocols.MessagePack/src/MessagePackHubProtocolOptions.cs @@ -9,6 +9,25 @@ namespace Microsoft.AspNetCore.SignalR { public class MessagePackHubProtocolOptions { - public IList FormatterResolvers { get; set; } = MessagePackHubProtocol.CreateDefaultFormatterResolvers(); + private IList _formatterResolvers; + + public IList FormatterResolvers + { + get + { + if (_formatterResolvers == null) + { + // The default set of resolvers trigger a static constructor that throws on AOT environments. + // This gives users the chance to use an AOT friendly formatter. + _formatterResolvers = MessagePackHubProtocol.CreateDefaultFormatterResolvers(); + } + + return _formatterResolvers; + } + set + { + _formatterResolvers = value; + } + } } } diff --git a/src/SignalR/common/SignalR.Common/test/Internal/Protocol/JsonHubProtocolTests.cs b/src/SignalR/common/SignalR.Common/test/Internal/Protocol/JsonHubProtocolTests.cs index f7dcdfa3c1..a3b8c4c098 100644 --- a/src/SignalR/common/SignalR.Common/test/Internal/Protocol/JsonHubProtocolTests.cs +++ b/src/SignalR/common/SignalR.Common/test/Internal/Protocol/JsonHubProtocolTests.cs @@ -101,6 +101,26 @@ namespace Microsoft.AspNetCore.SignalR.Common.Tests.Internal.Protocol Assert.Equal(expectedMessage, message); } + [Fact] + public void ReadCaseInsensitivePropertiesByDefault() + { + var input = Frame("{\"type\":2,\"invocationId\":\"123\",\"item\":{\"StrIngProp\":\"test\",\"DoublePrOp\":3.14159,\"IntProp\":43,\"DateTimeProp\":\"2019-06-03T22:00:00\",\"NuLLProp\":null,\"ByteARRProp\":\"AgQG\"}}"); + + var binder = new TestBinder(null, typeof(TemporaryCustomObject)); + var data = new ReadOnlySequence(Encoding.UTF8.GetBytes(input)); + JsonHubProtocol.TryParseMessage(ref data, binder, out var message); + + var streamItemMessage = Assert.IsType(message); + Assert.Equal(new TemporaryCustomObject() + { + ByteArrProp = new byte[] { 2, 4, 6 }, + IntProp = 43, + DoubleProp = 3.14159, + StringProp = "test", + DateTimeProp = DateTime.Parse("6/3/2019 10:00:00 PM") + }, streamItemMessage.Item); + } + public static IDictionary CustomProtocolTestData => new[] { new JsonProtocolTestData("InvocationMessage_HasFloatArgument", new InvocationMessage(null, "Target", new object[] { 1, "Foo", 2.0f }), true, true, "{\"type\":1,\"target\":\"Target\",\"arguments\":[1,\"Foo\",2]}"), diff --git a/src/SignalR/samples/ClientSample/HubSample.cs b/src/SignalR/samples/ClientSample/HubSample.cs index f37f6d1991..0810a30965 100644 --- a/src/SignalR/samples/ClientSample/HubSample.cs +++ b/src/SignalR/samples/ClientSample/HubSample.cs @@ -2,7 +2,6 @@ // 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; using Microsoft.AspNetCore.SignalR.Client; @@ -29,7 +28,9 @@ namespace ClientSample public static async Task ExecuteAsync(string baseUrl) { var uri = baseUrl == null ? new Uri("net.tcp://127.0.0.1:9001") : new Uri(baseUrl); + Console.WriteLine("Connecting to {0}", uri); + var connectionBuilder = new HubConnectionBuilder() .ConfigureLogging(logging => { @@ -52,88 +53,91 @@ namespace ClientSample connectionBuilder.WithAutomaticReconnect(); + using var closedTokenSource = new CancellationTokenSource(); var connection = connectionBuilder.Build(); - Console.CancelKeyPress += (sender, a) => + try { - a.Cancel = true; - connection.DisposeAsync().GetAwaiter().GetResult(); - }; - - // Set up handler - connection.On("Send", Console.WriteLine); - - CancellationTokenSource closedTokenSource = null; - - connection.Closed += e => - { - // This should never be null by the time this fires - closedTokenSource.Cancel(); - - Console.WriteLine("Connection closed..."); - return Task.CompletedTask; - }; - - - do - { - // Dispose the previous token - closedTokenSource?.Dispose(); - - // Create a new token for this run - closedTokenSource = new CancellationTokenSource(); - - // Connect to the server - } while (!await ConnectAsync(connection)); - - Console.WriteLine("Connected to {0}", uri); - - // Handle the connected connection - while (true) - { - try + Console.CancelKeyPress += (sender, a) => { + a.Cancel = true; + closedTokenSource.Cancel(); + connection.StopAsync().GetAwaiter().GetResult(); + }; + + // Set up handler + connection.On("Send", Console.WriteLine); + + connection.Closed += e => + { + Console.WriteLine("Connection closed..."); + closedTokenSource.Cancel(); + return Task.CompletedTask; + }; + + if (!await ConnectAsync(connection, closedTokenSource.Token)) + { + Console.WriteLine("Failed to establish a connection to '{0}' because the CancelKeyPress event fired first. Exiting...", uri); + return 0; + } + + Console.WriteLine("Connected to {0}", uri); + + // Handle the connected connection + while (true) + { + // If the underlying connection closes while waiting for user input, the user will not observe + // the connection close aside from "Connection closed..." being printed to the console. That's + // because cancelling Console.ReadLine() is a royal pain. var line = Console.ReadLine(); if (line == null || closedTokenSource.Token.IsCancellationRequested) { + Console.WriteLine("Exiting..."); break; } - await connection.InvokeAsync("Send", line); - } - catch (ObjectDisposedException) - { - // We're shutting down the client - break; - } - catch (Exception ex) - { - // Send could have failed because the connection closed - // Continue to loop because we should be reconnecting. - Console.WriteLine(ex); + try + { + await connection.InvokeAsync("Send", line); + } + catch when (closedTokenSource.IsCancellationRequested) + { + // We're shutting down the client + Console.WriteLine("Failed to send '{0}' because the CancelKeyPress event fired first. Exiting...", line); + break; + } + catch (Exception ex) + { + // Send could have failed because the connection closed + // Continue to loop because we should be reconnecting. + Console.WriteLine(ex); + } } } + finally + { + await connection.StopAsync(); + } return 0; } - private static async Task ConnectAsync(HubConnection connection) + private static async Task ConnectAsync(HubConnection connection, CancellationToken token) { // Keep trying to until we can start while (true) { try { - await connection.StartAsync(); + await connection.StartAsync(token); return true; } - catch (ObjectDisposedException) + catch when (token.IsCancellationRequested) { - // Client side killed the connection return false; } - catch (Exception) + catch { Console.WriteLine("Failed to connect, trying again in 5000(ms)"); diff --git a/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs b/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs index 16f1b8da63..9f7d6ffe56 100644 --- a/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs +++ b/src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs @@ -331,6 +331,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal } catch (Exception ex) { + Log.FailedInvokingHubMethod(_logger, hubMethodInvocationMessage.Target, ex); await SendInvocationError(hubMethodInvocationMessage.InvocationId, connection, ErrorMessageHelper.BuildErrorMessage($"An unexpected error occurred invoking '{hubMethodInvocationMessage.Target}' on the server.", ex, _enableDetailedErrors)); return; diff --git a/src/SignalR/server/SignalR/test/HubConnectionHandlerTests.cs b/src/SignalR/server/SignalR/test/HubConnectionHandlerTests.cs index d78cf6f668..25e47f03f4 100644 --- a/src/SignalR/server/SignalR/test/HubConnectionHandlerTests.cs +++ b/src/SignalR/server/SignalR/test/HubConnectionHandlerTests.cs @@ -859,10 +859,17 @@ namespace Microsoft.AspNetCore.SignalR.Tests [InlineData(nameof(MethodHub.MethodThatYieldsFailedTask), false)] public async Task HubMethodCanThrowOrYieldFailedTask(string methodName, bool detailedErrors) { + var hasErrorLog = false; bool ExpectedErrors(WriteContext writeContext) { - return writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && + var expected = writeContext.LoggerName == "Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher" && writeContext.EventId.Name == "FailedInvokingHubMethod"; + if (expected) + { + hasErrorLog = true; + return true; + } + return false; } using (StartVerifiableLog(ExpectedErrors)) @@ -898,6 +905,8 @@ namespace Microsoft.AspNetCore.SignalR.Tests await connectionHandlerTask.OrTimeout(); } } + + Assert.True(hasErrorLog); } [Fact] diff --git a/src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs b/src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs index b5cf8cfaa2..843f4ad377 100644 --- a/src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs +++ b/src/Tools/FirstRunCertGenerator/test/CertificateManagerTests.cs @@ -7,17 +7,20 @@ using System.Linq; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; -using System.Text; using Microsoft.AspNetCore.Testing.xunit; using Xunit; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Certificates.Generation.Tests { - public class CertificateManagerTests + public class CertificateManagerTests : IClassFixture { - public CertificateManagerTests(ITestOutputHelper output) + private CertFixture _fixture; + private CertificateManager _manager => _fixture.Manager; + + public CertificateManagerTests(ITestOutputHelper output, CertFixture fixture) { + _fixture = fixture; Output = output; } @@ -25,122 +28,31 @@ namespace Microsoft.AspNetCore.Certificates.Generation.Tests public ITestOutputHelper Output { get; } - [Fact(Skip = "True")] + [ConditionalFact] + [SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/6721")] public void EnsureCreateHttpsCertificate_CreatesACertificate_WhenThereAreNoHttpsCertificates() { try { // Arrange + _fixture.CleanupCertificates(); + const string CertificateName = nameof(EnsureCreateHttpsCertificate_CreatesACertificate_WhenThereAreNoHttpsCertificates) + ".cer"; - var manager = new CertificateManager(); - manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject); - } - - // Act + // Act DateTimeOffset now = DateTimeOffset.UtcNow; now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); - var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), CertificateName, trust: false, subject: TestCertificateSubject); - - // Assert - Assert.Equal(EnsureCertificateResult.Succeeded, result); - Assert.True(File.Exists(CertificateName)); - - var exportedCertificate = new X509Certificate2(File.ReadAllBytes(CertificateName)); - Assert.NotNull(exportedCertificate); - Assert.False(exportedCertificate.HasPrivateKey); - - var httpsCertificates = manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false); - var httpsCertificate = Assert.Single(httpsCertificates, c => c.Subject == TestCertificateSubject); - Assert.True(httpsCertificate.HasPrivateKey); - Assert.Equal(TestCertificateSubject, httpsCertificate.Subject); - Assert.Equal(TestCertificateSubject, httpsCertificate.Issuer); - Assert.Equal("sha256RSA", httpsCertificate.SignatureAlgorithm.FriendlyName); - Assert.Equal("1.2.840.113549.1.1.11", httpsCertificate.SignatureAlgorithm.Value); - - Assert.Equal(now.LocalDateTime, httpsCertificate.NotBefore); - Assert.Equal(now.AddYears(1).LocalDateTime, httpsCertificate.NotAfter); - Assert.Contains( - httpsCertificate.Extensions.OfType(), - e => e is X509BasicConstraintsExtension basicConstraints && - basicConstraints.Critical == true && - basicConstraints.CertificateAuthority == false && - basicConstraints.HasPathLengthConstraint == false && - basicConstraints.PathLengthConstraint == 0); - - Assert.Contains( - httpsCertificate.Extensions.OfType(), - e => e is X509KeyUsageExtension keyUsage && - keyUsage.Critical == true && - keyUsage.KeyUsages == (X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature)); - - Assert.Contains( - httpsCertificate.Extensions.OfType(), - e => e is X509EnhancedKeyUsageExtension enhancedKeyUsage && - enhancedKeyUsage.Critical == true && - enhancedKeyUsage.EnhancedKeyUsages.OfType().Single() is Oid keyUsage && - keyUsage.Value == "1.3.6.1.5.5.7.3.1"); - - // Subject alternative name - Assert.Contains( - httpsCertificate.Extensions.OfType(), - e => e.Critical == true && - e.Oid.Value == "2.5.29.17"); - - // ASP.NET HTTPS Development certificate extension - Assert.Contains( - httpsCertificate.Extensions.OfType(), - e => e.Critical == false && - e.Oid.Value == "1.3.6.1.4.1.311.84.1.1" && - Encoding.ASCII.GetString(e.RawData) == "ASP.NET Core HTTPS development certificate"); - - Assert.Equal(httpsCertificate.GetCertHashString(), exportedCertificate.GetCertHashString()); - - } - catch (Exception e) - { - Output.WriteLine(e.Message); - ListCertificates(Output); - throw; - } - } - - [ConditionalFact] - [SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/6721")] - public void EnsureCreateHttpsCertificate2_CreatesACertificate_WhenThereAreNoHttpsCertificates() - { - try - { - // Arrange - const string CertificateName = nameof(EnsureCreateHttpsCertificate_CreatesACertificate_WhenThereAreNoHttpsCertificates) + ".cer"; - var manager = new CertificateManager(); - manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject); - } - - // Act - DateTimeOffset now = DateTimeOffset.UtcNow; - now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); - var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate2(now, now.AddYears(1), CertificateName, trust: false, subject: TestCertificateSubject); + var result = _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), CertificateName, trust: false, subject: TestCertificateSubject); // Assert Assert.Equal(EnsureCertificateResult.Succeeded, result.ResultCode); - Assert.NotNull(result.Diagnostics); - Assert.NotEmpty(result.Diagnostics.Messages); - Assert.Empty(result.Diagnostics.Exceptions); - Assert.True(File.Exists(CertificateName)); var exportedCertificate = new X509Certificate2(File.ReadAllBytes(CertificateName)); Assert.NotNull(exportedCertificate); Assert.False(exportedCertificate.HasPrivateKey); - var httpsCertificates = manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false); + var httpsCertificates = _manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false); var httpsCertificate = Assert.Single(httpsCertificates, c => c.Subject == TestCertificateSubject); Assert.True(httpsCertificate.HasPrivateKey); Assert.Equal(TestCertificateSubject, httpsCertificate.Subject); @@ -182,7 +94,7 @@ namespace Microsoft.AspNetCore.Certificates.Generation.Tests httpsCertificate.Extensions.OfType(), e => e.Critical == false && e.Oid.Value == "1.3.6.1.4.1.311.84.1.1" && - Encoding.ASCII.GetString(e.RawData) == "ASP.NET Core HTTPS development certificate"); + e.RawData[0] == _manager.AspNetHttpsCertificateVersion); Assert.Equal(httpsCertificate.GetCertHashString(), exportedCertificate.GetCertHashString()); @@ -211,32 +123,27 @@ namespace Microsoft.AspNetCore.Certificates.Generation.Tests } } - [Fact(Skip = "true")] + [ConditionalFact] + [SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/6721")] public void EnsureCreateHttpsCertificate_DoesNotCreateACertificate_WhenThereIsAnExistingHttpsCertificates() { // Arrange const string CertificateName = nameof(EnsureCreateHttpsCertificate_DoesNotCreateACertificate_WhenThereIsAnExistingHttpsCertificates) + ".pfx"; var certificatePassword = Guid.NewGuid().ToString(); - var manager = new CertificateManager(); - - manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject); - } + _fixture.CleanupCertificates(); DateTimeOffset now = DateTimeOffset.UtcNow; now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); - manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: false, subject: TestCertificateSubject); + _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: false, subject: TestCertificateSubject); - var httpsCertificate = manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false).Single(c => c.Subject == TestCertificateSubject); + var httpsCertificate = _manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false).Single(c => c.Subject == TestCertificateSubject); // Act - var result = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), CertificateName, trust: false, includePrivateKey: true, password: certificatePassword, subject: TestCertificateSubject); + var result = _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), CertificateName, trust: false, includePrivateKey: true, password: certificatePassword, subject: TestCertificateSubject); // Assert - Assert.Equal(EnsureCertificateResult.ValidCertificatePresent, result); + Assert.Equal(EnsureCertificateResult.ValidCertificatePresent, result.ResultCode); Assert.True(File.Exists(CertificateName)); var exportedCertificate = new X509Certificate2(File.ReadAllBytes(CertificateName), certificatePassword); @@ -247,39 +154,125 @@ namespace Microsoft.AspNetCore.Certificates.Generation.Tests Assert.Equal(httpsCertificate.GetCertHashString(), exportedCertificate.GetCertHashString()); } - [Fact(Skip = "Requires user interaction")] - public void EnsureAspNetCoreHttpsDevelopmentCertificate_ReturnsCorrectResult_WhenUserCancelsTrustStepOnWindows() + [ConditionalFact] + [SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/6721")] + public void EnsureCreateHttpsCertificate_ReturnsExpiredCertificateIfVersionIsIncorrect() { - var manager = new CertificateManager(); - - manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject); - } + _fixture.CleanupCertificates(); DateTimeOffset now = DateTimeOffset.UtcNow; now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); - var trustFailed = manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: true, subject: TestCertificateSubject); + _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: false, subject: TestCertificateSubject); - Assert.Equal(EnsureCertificateResult.UserCancelledTrustStep, trustFailed); + _manager.AspNetHttpsCertificateVersion = 2; + + var httpsCertificateList = _manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true); + Assert.Empty(httpsCertificateList); + } + + [ConditionalFact] + [SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/6721")] + public void EnsureCreateHttpsCertificate_ReturnsExpiredCertificateForEmptyVersionField() + { + _fixture.CleanupCertificates(); + + DateTimeOffset now = DateTimeOffset.UtcNow; + now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); + _manager.AspNetHttpsCertificateVersion = 0; + _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: false, subject: TestCertificateSubject); + + _manager.AspNetHttpsCertificateVersion = 1; + + var httpsCertificateList = _manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true); + Assert.Empty(httpsCertificateList); + } + + [ConditionalFact] + [SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/6721")] + public void EnsureCreateHttpsCertificate_ReturnsValidIfVersionIsZero() + { + _fixture.CleanupCertificates(); + + DateTimeOffset now = DateTimeOffset.UtcNow; + now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); + _manager.AspNetHttpsCertificateVersion = 0; + _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: false, subject: TestCertificateSubject); + + var httpsCertificateList = _manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true); + Assert.NotEmpty(httpsCertificateList); + } + + [ConditionalFact] + [SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/6721")] + public void EnsureCreateHttpsCertificate_ReturnValidIfCertIsNewer() + { + _fixture.CleanupCertificates(); + + DateTimeOffset now = DateTimeOffset.UtcNow; + now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); + _manager.AspNetHttpsCertificateVersion = 2; + _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: false, subject: TestCertificateSubject); + + _manager.AspNetHttpsCertificateVersion = 1; + var httpsCertificateList = _manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true); + Assert.NotEmpty(httpsCertificateList); + } + + [Fact(Skip = "Requires user interaction")] + public void EnsureAspNetCoreHttpsDevelopmentCertificate_ReturnsCorrectResult_WhenUserCancelsTrustStepOnWindows() + { + _fixture.CleanupCertificates(); + + DateTimeOffset now = DateTimeOffset.UtcNow; + now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); + var trustFailed = _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: true, subject: TestCertificateSubject); + + Assert.Equal(EnsureCertificateResult.UserCancelledTrustStep, trustFailed.ResultCode); } [Fact(Skip = "Requires user interaction")] public void EnsureAspNetCoreHttpsDevelopmentCertificate_CanRemoveCertificates() { - var manager = new CertificateManager(); + _fixture.CleanupCertificates(); DateTimeOffset now = DateTimeOffset.UtcNow; now = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0, now.Offset); - manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: true, subject: TestCertificateSubject); + _manager.EnsureAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1), path: null, trust: true, subject: TestCertificateSubject); - manager.CleanupHttpsCertificates(TestCertificateSubject); + _manager.CleanupHttpsCertificates(TestCertificateSubject); - Assert.Empty(manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false).Where(c => c.Subject == TestCertificateSubject)); + Assert.Empty(_manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: false).Where(c => c.Subject == TestCertificateSubject)); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - Assert.Empty(manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, isValid: false).Where(c => c.Subject == TestCertificateSubject)); + Assert.Empty(_manager.ListCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, isValid: false).Where(c => c.Subject == TestCertificateSubject)); + } + } + } + + public class CertFixture : IDisposable + { + public const string TestCertificateSubject = "CN=aspnet.test"; + + public CertFixture() + { + Manager = new CertificateManager(); + + CleanupCertificates(); + } + + internal CertificateManager Manager { get; set; } + + public void Dispose() + { + CleanupCertificates(); + } + + internal void CleanupCertificates() + { + Manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, TestCertificateSubject); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Manager.RemoveAllCertificates(CertificatePurpose.HTTPS, StoreName.Root, StoreLocation.CurrentUser, TestCertificateSubject); } } } diff --git a/src/Tools/Tools.sln b/src/Tools/Tools.sln index a2e2452067..77867dcf59 100644 --- a/src/Tools/Tools.sln +++ b/src/Tools/Tools.sln @@ -7,6 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch", "dotnet-watc EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-watch.Tests", "dotnet-watch\test\dotnet-watch.Tests.csproj", "{63F7E822-D1E2-4C41-8ABF-60B9E3A9C54C}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-dev-certs", "dotnet-dev-certs\src\dotnet-dev-certs.csproj", "{0D6D5693-7E0C-4FE8-B4AA-21207B2650AA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.XPlat", "FirstRunCertGenerator\src\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj", "{7BBDBDA2-299F-4C36-8338-23C525901DE0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DeveloperCertificates.XPlat.Tests", "FirstRunCertGenerator\test\Microsoft.AspNetCore.DeveloperCertificates.XPlat.Tests.csproj", "{1EC6FA27-40A5-433F-8CA1-636E7ED8863E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +27,18 @@ Global {63F7E822-D1E2-4C41-8ABF-60B9E3A9C54C}.Debug|Any CPU.Build.0 = Debug|Any CPU {63F7E822-D1E2-4C41-8ABF-60B9E3A9C54C}.Release|Any CPU.ActiveCfg = Release|Any CPU {63F7E822-D1E2-4C41-8ABF-60B9E3A9C54C}.Release|Any CPU.Build.0 = Release|Any CPU + {0D6D5693-7E0C-4FE8-B4AA-21207B2650AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0D6D5693-7E0C-4FE8-B4AA-21207B2650AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0D6D5693-7E0C-4FE8-B4AA-21207B2650AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0D6D5693-7E0C-4FE8-B4AA-21207B2650AA}.Release|Any CPU.Build.0 = Release|Any CPU + {7BBDBDA2-299F-4C36-8338-23C525901DE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7BBDBDA2-299F-4C36-8338-23C525901DE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7BBDBDA2-299F-4C36-8338-23C525901DE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7BBDBDA2-299F-4C36-8338-23C525901DE0}.Release|Any CPU.Build.0 = Release|Any CPU + {1EC6FA27-40A5-433F-8CA1-636E7ED8863E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1EC6FA27-40A5-433F-8CA1-636E7ED8863E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1EC6FA27-40A5-433F-8CA1-636E7ED8863E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1EC6FA27-40A5-433F-8CA1-636E7ED8863E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Tools/dotnet-dev-certs/src/Program.cs b/src/Tools/dotnet-dev-certs/src/Program.cs index 170e11b09d..3854c4c59c 100644 --- a/src/Tools/dotnet-dev-certs/src/Program.cs +++ b/src/Tools/dotnet-dev-certs/src/Program.cs @@ -81,6 +81,7 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools (check.HasValue() && (exportPath.HasValue() || password.HasValue() || clean.HasValue()))) { reporter.Error(@"Incompatible set of flags. Sample usages +'dotnet dev-certs https' 'dotnet dev-certs https --clean' 'dotnet dev-certs https --check --trust' 'dotnet dev-certs https -ep ./certificate.pfx -p password --trust'"); @@ -133,7 +134,7 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools } manager.CleanupHttpsCertificates(); - reporter.Verbose("HTTPS development certificates successfully removed from the machine."); + reporter.Output("HTTPS development certificates successfully removed from the machine."); return Success; } catch(Exception e) @@ -152,12 +153,12 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools var certificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, StoreName.My, StoreLocation.CurrentUser, isValid: true); if (certificates.Count == 0) { - reporter.Verbose("No valid certificate found."); + reporter.Output("No valid certificate found."); return ErrorNoValidCertificateFound; } else { - reporter.Verbose("A valid certificate was found."); + reporter.Output("A valid certificate was found."); } if (trust != null && trust.HasValue()) @@ -166,13 +167,13 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools var trustedCertificates = certificateManager.ListCertificates(CertificatePurpose.HTTPS, store, StoreLocation.CurrentUser, isValid: true); if (!certificates.Any(c => certificateManager.IsTrusted(c))) { - reporter.Verbose($@"The following certificates were found, but none of them is trusted: + reporter.Output($@"The following certificates were found, but none of them is trusted: {string.Join(Environment.NewLine, certificates.Select(c => $"{c.Subject} - {c.Thumbprint}"))}"); return ErrorCertificateNotTrusted; } else { - reporter.Verbose("A trusted certificate was found."); + reporter.Output("A trusted certificate was found."); } } @@ -207,7 +208,9 @@ namespace Microsoft.AspNetCore.DeveloperCertificates.Tools password.HasValue(), password.Value()); - switch (result) + reporter.Verbose(string.Join(Environment.NewLine, result.Diagnostics.Messages)); + + switch (result.ResultCode) { case EnsureCertificateResult.Succeeded: reporter.Output("The HTTPS developer certificate was generated successfully.");