diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 000000000..776f337d8 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,20 @@ +init: + - git config --global core.autocrlf true +branches: + only: + - main + - /^(.*\/)?ci-.*$/ + - /^rel\/.*/ +configuration: + - CodeAnalysis + - Release +matrix: + fast_finish: true +before_build: + - cmd: .\build.cmd EnableSkipStrongNames +build_script: + - cmd: .\build.cmd UnitTest /P:Configuration=%Configuration% +clone_depth: 1 +test: off +deploy: off +os: Visual Studio 2017 diff --git a/.azuredevops/dependabot.yml b/.azuredevops/dependabot.yml new file mode 100644 index 000000000..e99cd24bd --- /dev/null +++ b/.azuredevops/dependabot.yml @@ -0,0 +1,3 @@ +version: 2 +enable-campaigned-updates: false +enable-security-updates: false diff --git a/.config/CredScanSuppressions.json b/.config/CredScanSuppressions.json new file mode 100644 index 000000000..8db08e538 --- /dev/null +++ b/.config/CredScanSuppressions.json @@ -0,0 +1,29 @@ +{ + "tool": "Credential Scanner", + "suppressions": [ + { + "placeholder": "abcdefg", + "_justification": "This is a fake password used in test code." + }, + { + "placeholder": "Pa$$AAECAw==", + "_justification": "This is a fake password used in test code." + }, + { + "placeholder": "ALyuoraY/cIWD1hjo+K81/pf83qo6Q6T+UBYcXN9P3A9WHLvEY10f+lwW5qPG6h9xw==", + "_justification": "This is a fake hashed password used in test code." + }, + { + "placeholder": "abcdefg123", + "_justification": "This is a fake password used in test code." + }, + { + "placeholder": "3e29b24f825e737d97aed5eb62df5076", + "_justification": "This is a fake password used in test code." + }, + { + "placeholder": "My Password", + "_justification": "This is a fake password used in test code." + } + ] +} \ No newline at end of file diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json new file mode 100644 index 000000000..cb7d8b10a --- /dev/null +++ b/.config/tsaoptions.json @@ -0,0 +1,12 @@ +{ + "areaPath": "DevDiv\\ASP.NET Core\\Policy Violations", + "codebaseName": "AspNetWebStack", + "instanceUrl": "https://devdiv.visualstudio.com/", + "iterationPath": "DevDiv", + "notificationAliases": [ + "aspnetcore-build@microsoft.com" + ], + "projectName": "DEVDIV", + "repositoryName": "AspNetWebStack", + "template": "TFSDEVDIV" +} diff --git a/.gitignore b/.gitignore index 4d0b89238..9f67f0ee8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,20 @@ -[Bb]in -[Oo]bj -[Tt]est[Rr]esults -*.suo -*.user +.msbuild/ +.vs/ +bin/ +obj/ +packages/ + *.[Cc]ache -*[Rr]esharper* -packages -NuGet.exe -_[Ss]cripts -*.exe +*.binlog *.dll -*.nupkg *.dot[Cc]over -*.vsp -*.psess +*.exe +*.nupkg *.orig +*.psess *.sln.ide -.vs/ -project.lock.json \ No newline at end of file +*.suo +*.user +*.vsp +*[Rr]esharper* +*launchSettings.json diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config deleted file mode 100644 index 6ff25f633..000000000 --- a/.nuget/NuGet.Config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.nuget/packages.config b/.nuget/packages.config index d666c4dd7..a8fe9612a 100644 --- a/.nuget/packages.config +++ b/.nuget/packages.config @@ -2,6 +2,6 @@ - - + + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..a9a61ca73 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: csharp +sudo: false +dist: trusty +mono: none +os: + - linux +branches: + only: + - not.a.branch +script: + - echo Skipping builds for now. diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md new file mode 100644 index 000000000..775f221c9 --- /dev/null +++ b/CODE-OF-CONDUCT.md @@ -0,0 +1,6 @@ +# Code of Conduct + +This project has adopted the code of conduct defined by the Contributor Covenant +to clarify expected behavior in our community. + +For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 87a1e8276..89c98a590 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,6 @@ One of the easiest ways to contribute is to participate in discussions and discuss issues. You can also contribute by submitting pull requests with code changes. - ## Bugs and feature requests? For non-security related bugs please log a new issue in this repo. @@ -12,10 +11,10 @@ Security issues and bugs should be reported privately, via email, to the Microso ## Other discussions Our team members also monitor several other discussion forums: -* [ASP.NET Core forum](https://forums.asp.net/1255.aspx/1?ASP+NET+5) -* [StackOverflow](https://stackoverflow.com/) with the [`asp.net-core`](https://stackoverflow.com/questions/tagged/asp.net-core), [`asp.net-core-mvc`](https://stackoverflow.com/questions/tagged/asp.net-core-mvc), or [`entity-framework-core`](https://stackoverflow.com/questions/tagged/entity-framework-core) tags. -* [JabbR chat room](https://jabbr.net/#/rooms/AspNetCore) for real-time discussions with the community and the people who work on the project - +* [ASP.NET MVC forum](https://forums.asp.net/1146.aspx/1?MVC) +* [ASP.NET Web API forum](https://forums.asp.net/1246.aspx/1?Web+API) +* [ASP.NET Web Pages forum](https://forums.asp.net/1224.aspx/1?ASP+NET+Web+Pages) +* [StackOverflow](https://stackoverflow.com/) with the [`asp.net`](https://stackoverflow.com/questions/tagged/asp.net), [`asp.net-mvc`](https://stackoverflow.com/questions/tagged/asp.net-mvc), [`asp.net-web-api`](https://stackoverflow.com/questions/tagged/asp.net-web-api), [`asp.net-webpages`](https://stackoverflow.com/questions/tagged/asp.net-webpages) or [`razor`](https://stackoverflow.com/questions/tagged/razor) tags. ## Filing issues When filing issues, please use our [bug filing templates](https://github.com/aspnet/Home/wiki/Functional-bug-template). @@ -32,7 +31,6 @@ Here are questions you can answer before you file a bug to make sure you're not GitHub supports [markdown](https://help.github.com/articles/github-flavored-markdown/), so when filing bugs make sure you check the formatting before clicking submit. - ## Contributing code and content You will need to sign a [Contributor License Agreement](https://cla2.dotnetfoundation.org/) before submitting your pull request. To complete the Contributor License Agreement (CLA), you will need to submit a request via the form and then electronically sign the Contributor License Agreement when you receive the email containing the link to the document. This needs to only be done once for any .NET Foundation OSS project. @@ -58,4 +56,3 @@ Addresses #bugnumber (in this specific format) - Tests only need to be present for issues that need to be verified by QA (e.g. not tasks) - If there is a scenario that is far too hard to test there does not need to be a test for it. - "Too hard" is determined by the team as a whole. - diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..fef50e3d3 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,16 @@ + + + + + + 16.0 + + true + + false + + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 000000000..080cbd855 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,3 @@ + + + diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 000000000..837d83954 --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index a6a2a88de..f4c49434b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ -ASP.NET MVC, Web API, Web Pages, and Razor -=== +# ASP.NET MVC, Web API, Web Pages, and Razor -## Note: This repo is for ASP.NET MVC 5.x, Web API 2.x, and Web Pages 3.x. For ASP.NET Core MVC, check the [MVC repo](https://github.com/aspnet/Mvc). +## Note: This repo is for ASP.NET MVC 5.x, Web API 2.x, and Web Pages 3.x. For ASP.NET Core MVC, check the [AspNetCore repo](https://github.com/aspnet/AspNetCore). ASP.NET MVC is a web framework that gives you a powerful, patterns-based way to build dynamic websites and Web APIs. ASP.NET MVC enables a clean separation of concerns and gives you full control over markup. @@ -12,6 +11,19 @@ This repo includes: * ASP.NET Web Pages 3.x * ASP.NET Razor 3.x -### Nightly builds +### Contributing -The latest built and tested packages from this repo are available on this MyGet feed: https://myget.org/gallery/aspnetwebstacknightly +Check out the [contributing](CONTRIBUTING.md) page to see the best places to log issues and start discussions. + +### Tags and releases + +Git tag or branch|Other products|MVC package versions|Web API package (product) versions|Web Pages package versions +--------|--------------|------------|------------|------------ +[v2.0.4](https://github.com/aspnet/AspNetWebStack/tree/v2.0.4)||4.0.40804|4.0.30506|2.0.30506 +[v2.1](https://github.com/aspnet/AspNetWebStack/tree/v2.1)|ASP.NET and Web Tools 2012.2, VS 2012 Update 2 (not on http://nuget.org)|v4 2012.2 Update RTM|v1 2012.2 Update RTM|v2 2012.2 Update RTM +[v3.0.2](https://github.com/aspnet/AspNetWebStack/tree/v3.0.2)||5.0.2|5.0.1 (2.0.1)|3.0.1 +[v3.1.3](https://github.com/aspnet/AspNetWebStack/tree/v3.1.3)||5.1.3|5.1.2 (2.1.2)|3.1.2 +[v3.2.6](https://github.com/aspnet/AspNetWebStack/tree/v3.2.6)||5.2.6|5.2.6|3.2.6 +[v3.2.7](https://github.com/aspnet/AspNetWebStack/tree/v3.2.7)||5.2.7|5.2.7|3.2.7 +[v3.2.8](https://github.com/aspnet/AspNetWebStack/tree/v3.2.8)||5.2.8|5.2.8|3.2.8 +[main](https://github.com/aspnet/AspNetWebStack/tree/main)|New work e.g. MVC 5.2.9-preview1|||| diff --git a/Runtime.NetFramework.slnf b/Runtime.NetFramework.slnf new file mode 100644 index 000000000..7b79711ff --- /dev/null +++ b/Runtime.NetFramework.slnf @@ -0,0 +1,57 @@ +{ + "solution": { + "path": "Runtime.sln", + "projects": [ + "src\\Microsoft.AspNet.Facebook\\Microsoft.AspNet.Facebook.csproj", + "src\\Microsoft.Web.Helpers\\Microsoft.Web.Helpers.csproj", + "src\\Microsoft.Web.Mvc\\Microsoft.Web.Mvc.csproj", + "src\\Microsoft.Web.WebPages.OAuth\\Microsoft.Web.WebPages.OAuth.csproj", + "src\\System.Net.Http.Formatting\\System.Net.Http.Formatting.csproj", + "src\\System.Web.Cors\\System.Web.Cors.csproj", + "src\\System.Web.Helpers\\System.Web.Helpers.csproj", + "src\\System.Web.Http.Cors\\System.Web.Http.Cors.csproj", + "src\\System.Web.Http.Owin\\System.Web.Http.Owin.csproj", + "src\\System.Web.Http.SelfHost\\System.Web.Http.SelfHost.csproj", + "src\\System.Web.Http.SignalR\\System.Web.Http.SignalR.csproj", + "src\\System.Web.Http.Tracing\\System.Web.Http.Tracing.csproj", + "src\\System.Web.Http.WebHost\\System.Web.Http.WebHost.csproj", + "src\\System.Web.Http\\System.Web.Http.csproj", + "src\\System.Web.Mvc\\System.Web.Mvc.csproj", + "src\\System.Web.Razor\\System.Web.Razor.csproj", + "src\\System.Web.WebPages.Administration\\System.Web.WebPages.Administration.csproj", + "src\\System.Web.WebPages.Deployment\\System.Web.WebPages.Deployment.csproj", + "src\\System.Web.WebPages.Razor\\System.Web.WebPages.Razor.csproj", + "src\\System.Web.WebPages\\System.Web.WebPages.csproj", + "src\\WebApiHelpPage\\VB\\WebApiHelpPageVB.vbproj", + "src\\WebApiHelpPage\\WebApiHelpPage.csproj", + "src\\WebMatrix.Data\\WebMatrix.Data.csproj", + "src\\WebMatrix.WebData\\WebMatrix.WebData.csproj", + "test\\Microsoft.AspNet.Facebook.Test\\Microsoft.AspNet.Facebook.Test.csproj", + "test\\Microsoft.TestCommon\\Microsoft.TestCommon.csproj", + "test\\Microsoft.Web.Helpers.Test\\Microsoft.Web.Helpers.Test.csproj", + "test\\Microsoft.Web.Mvc.Test\\Microsoft.Web.Mvc.Test.csproj", + "test\\Microsoft.Web.WebPages.OAuth.Test\\Microsoft.Web.WebPages.OAuth.Test.csproj", + "test\\System.Net.Http.Formatting.Test\\System.Net.Http.Formatting.Test.csproj", + "test\\System.Web.Cors.Test\\System.Web.Cors.Test.csproj", + "test\\System.Web.Helpers.Test\\System.Web.Helpers.Test.csproj", + "test\\System.Web.Http.Cors.Test\\System.Web.Http.Cors.Test.csproj", + "test\\System.Web.Http.Integration.Test\\System.Web.Http.Integration.Test.csproj", + "test\\System.Web.Http.Owin.Test\\System.Web.Http.Owin.Test.csproj", + "test\\System.Web.Http.SelfHost.Test\\System.Web.Http.SelfHost.Test.csproj", + "test\\System.Web.Http.SignalR.Test\\System.Web.Http.SignalR.Test.csproj", + "test\\System.Web.Http.Test\\System.Web.Http.Test.csproj", + "test\\System.Web.Http.Tracing.Test\\System.Web.Http.Tracing.Test.csproj", + "test\\System.Web.Http.WebHost.Test\\System.Web.Http.WebHost.Test.csproj", + "test\\System.Web.Mvc.Test\\System.Web.Mvc.Test.csproj", + "test\\System.Web.Razor.Test\\System.Web.Razor.Test.csproj", + "test\\System.Web.WebPages.Administration.Test\\System.Web.WebPages.Administration.Test.csproj", + "test\\System.Web.WebPages.Deployment.Test\\System.Web.WebPages.Deployment.Test.csproj", + "test\\System.Web.WebPages.Razor.Test\\System.Web.WebPages.Razor.Test.csproj", + "test\\System.Web.WebPages.Test\\System.Web.WebPages.Test.csproj", + "test\\WebApiHelpPage.Test\\WebApiHelpPage.Test.csproj", + "test\\WebApiHelpPage.VB.Test\\WebApiHelpPage.VB.Test.csproj", + "test\\WebMatrix.Data.Test\\WebMatrix.Data.Test.csproj", + "test\\WebMatrix.WebData.Test\\WebMatrix.WebData.Test.csproj" + ] + } +} \ No newline at end of file diff --git a/Runtime.NetStandard.slnf b/Runtime.NetStandard.slnf new file mode 100644 index 000000000..b8270ab3e --- /dev/null +++ b/Runtime.NetStandard.slnf @@ -0,0 +1,12 @@ +{ + "solution": { + "path": "Runtime.sln", + "projects": [ + "src\\System.Net.Http.Formatting.ns1_3\\System.Net.Http.Formatting.ns1_3.csproj", + "src\\System.Net.Http.Formatting.ns2_0\\System.Net.Http.Formatting.ns2_0.csproj", + "test\\Microsoft.TestCommon\\Microsoft.TestCommon.csproj", + "test\\System.Net.Http.Formatting.ns1_3.Test\\System.Net.Http.Formatting.ns1_3.Test.csproj", + "test\\System.Net.Http.Formatting.ns2_0.Test\\System.Net.Http.Formatting.ns2_0.Test.csproj" + ] + } +} \ No newline at end of file diff --git a/Runtime.msbuild b/Runtime.msbuild index 0f4fc9eee..815aaf93e 100644 --- a/Runtime.msbuild +++ b/Runtime.msbuild @@ -8,25 +8,16 @@ Release true true - true true false + false + false $(MSBuildThisFileDirectory)bin\$(Configuration)\test\TestResults\ $(MSBuildThisFileDirectory)packages\Microsoft.Web.SkipStrongNames.1.0.0\tools\SkipStrongNames.exe $(MSBuildThisFileDirectory)tools\SkipStrongNames.xml .nuget\NuGet.exe - - - $(BuildInParallel) - - - $(BuildInParallel) - true - - - @@ -47,9 +38,8 @@ @@ -59,55 +49,100 @@ - + + + <_Testing_NetStandard1_3 Include="true;false" /> + + - - - + + + + + + + - + + - $(MsBuildThisFileDirectory)tools\src\Microsoft.Web.FxCop\ - $(MsBuildThisFileDirectory)packages\CustomFxCopRules + $(MSBuildThisFileDirectory)tools\src\Microsoft.Web.FxCop\ + $(MSBuildThisFileDirectory)packages\CustomFxCopRules - + - - - + + + + + + + Projects="Runtime.sln" + BuildInParallel="$(BuildInParallel)" + Targets="Build" + Properties="Configuration=$(Configuration);CodeAnalysis=$(CodeAnalysis);StyleCopEnabled=$(StyleCopEnabled); + VisualStudioVersion=$(VisualStudioVersion)" /> - - - + - - - TestAssembly=%(TestDLLsXunit.FullPath);XmlPath=$(TestResultsDirectory)%(TestDLLsXunit.FileName)-XunitResults.xml - + <_TestDLLsXunit Include="bin\$(Configuration)\test\*.Test.dll; + bin\$(Configuration)\test\*\net4*\*.Test.dll" /> + <_XunitProject Include="tools\WebStack.testing.targets"> + TestAssembly=%(_TestDLLsXunit.FullPath); + XmlPath=$(TestResultsDirectory)%(_TestDLLsXunit.FileName)-XunitResults.xml + + + <_VSTestDLLs Include="bin\$(Configuration)\test\ns1_3\**\*.Test.dll; + bin\$(Configuration)\test\ns2_0\**\*.Test.dll" + Exclude="bin\$(Configuration)\test\*\net4*\*.Test.dll" /> + <_XunitProject Include="tools\WebStack.testing.targets"> + TestAssembly=%(_VSTestDLLs.FullPath); + XmlPath=$(TestResultsDirectory)%(_VSTestDLLs.FileName)-$([System.String]::Copy('%(_VSTestDLLs.RecursiveDir)').Trim('\\'))-XunitResults.xml; + UseVSTest=true + - + - + + + @@ -117,7 +152,11 @@ - + + + + diff --git a/Runtime.sln b/Runtime.sln index 53af9bb27..56de063a7 100644 --- a/Runtime.sln +++ b/Runtime.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 -MinimumVisualStudioVersion = 10.0.40219.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.27016.1 +MinimumVisualStudioVersion = 15.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A9836F9E-6DB3-4D9F-ADCA-CF42D8C8BA93}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C40883CD-366D-4534-8B58-3EA0D13136DF}" @@ -57,7 +57,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Web.Http.Test", "tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Http.Formatting", "src\System.Net.Http.Formatting\System.Net.Http.Formatting.csproj", "{668E9021-CE84-49D9-98FB-DF125A9FCDB0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.TestCommon", "test\Microsoft.TestCommon\Microsoft.TestCommon.csproj", "{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestCommon", "test\Microsoft.TestCommon\Microsoft.TestCommon.csproj", "{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Http.Formatting.Test", "test\System.Net.Http.Formatting.Test\System.Net.Http.Formatting.Test.csproj", "{7AF77741-9158-4D5F-8782-8F21FADF025F}" EndProject @@ -95,9 +95,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Web.Http.Owin", "src EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Web.Http.Owin.Test", "test\System.Web.Http.Owin.Test\System.Web.Http.Owin.Test.csproj", "{C19267DD-3984-430C-AE18-4034F85DE4E5}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{CB34D534-9A09-4EE4-B350-C1C23AFBF5EE}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{CB34D534-9A09-4EE4-B350-C1C23AFBF5EE}" ProjectSection(SolutionItems) = preProject - .nuget\NuGet.Config = .nuget\NuGet.Config + global.json = global.json + NuGet.Config = NuGet.Config .nuget\packages.config = .nuget\packages.config EndProjectSection EndProject @@ -113,6 +114,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Facebook", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Facebook.Test", "test\Microsoft.AspNet.Facebook.Test\Microsoft.AspNet.Facebook.Test.csproj", "{C3BEF382-C7C4-454D-B017-1EAC03E9A82C}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Net.Http.Formatting.ns1_3", "src\System.Net.Http.Formatting.ns1_3\System.Net.Http.Formatting.ns1_3.csproj", "{5ABD9968-F3A3-4967-B768-A6142F69759E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Net.Http.Formatting.ns2_0", "src\System.Net.Http.Formatting.ns2_0\System.Net.Http.Formatting.ns2_0.csproj", "{9AAFB58C-B8C1-4D7F-80E6-7B95C94A829B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Net.Http.Formatting.ns1_3.Test", "test\System.Net.Http.Formatting.ns1_3.Test\System.Net.Http.Formatting.ns1_3.Test.csproj", "{A1A20049-04C2-4676-93CF-92449C4BBAA9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Net.Http.Formatting.ns2_0.Test", "test\System.Net.Http.Formatting.ns2_0.Test\System.Net.Http.Formatting.ns2_0.Test.csproj", "{6C320AD9-F380-4F8B-85F9-0689F88766EC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution CodeAnalysis|Any CPU = CodeAnalysis|Any CPU @@ -420,6 +429,30 @@ Global {C3BEF382-C7C4-454D-B017-1EAC03E9A82C}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3BEF382-C7C4-454D-B017-1EAC03E9A82C}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3BEF382-C7C4-454D-B017-1EAC03E9A82C}.Release|Any CPU.Build.0 = Release|Any CPU + {5ABD9968-F3A3-4967-B768-A6142F69759E}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {5ABD9968-F3A3-4967-B768-A6142F69759E}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {5ABD9968-F3A3-4967-B768-A6142F69759E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5ABD9968-F3A3-4967-B768-A6142F69759E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5ABD9968-F3A3-4967-B768-A6142F69759E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5ABD9968-F3A3-4967-B768-A6142F69759E}.Release|Any CPU.Build.0 = Release|Any CPU + {9AAFB58C-B8C1-4D7F-80E6-7B95C94A829B}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {9AAFB58C-B8C1-4D7F-80E6-7B95C94A829B}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {9AAFB58C-B8C1-4D7F-80E6-7B95C94A829B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AAFB58C-B8C1-4D7F-80E6-7B95C94A829B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AAFB58C-B8C1-4D7F-80E6-7B95C94A829B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AAFB58C-B8C1-4D7F-80E6-7B95C94A829B}.Release|Any CPU.Build.0 = Release|Any CPU + {A1A20049-04C2-4676-93CF-92449C4BBAA9}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {A1A20049-04C2-4676-93CF-92449C4BBAA9}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {A1A20049-04C2-4676-93CF-92449C4BBAA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A1A20049-04C2-4676-93CF-92449C4BBAA9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1A20049-04C2-4676-93CF-92449C4BBAA9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A1A20049-04C2-4676-93CF-92449C4BBAA9}.Release|Any CPU.Build.0 = Release|Any CPU + {6C320AD9-F380-4F8B-85F9-0689F88766EC}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {6C320AD9-F380-4F8B-85F9-0689F88766EC}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {6C320AD9-F380-4F8B-85F9-0689F88766EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C320AD9-F380-4F8B-85F9-0689F88766EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C320AD9-F380-4F8B-85F9-0689F88766EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C320AD9-F380-4F8B-85F9-0689F88766EC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -475,5 +508,12 @@ Global {1E89A3E9-0A7F-418F-B4BE-6E38A6315373} = {C40883CD-366D-4534-8B58-3EA0D13136DF} {821A136C-7C6F-44C6-A9E6-C39B5BFB1483} = {A9836F9E-6DB3-4D9F-ADCA-CF42D8C8BA93} {C3BEF382-C7C4-454D-B017-1EAC03E9A82C} = {C40883CD-366D-4534-8B58-3EA0D13136DF} + {5ABD9968-F3A3-4967-B768-A6142F69759E} = {A9836F9E-6DB3-4D9F-ADCA-CF42D8C8BA93} + {9AAFB58C-B8C1-4D7F-80E6-7B95C94A829B} = {A9836F9E-6DB3-4D9F-ADCA-CF42D8C8BA93} + {A1A20049-04C2-4676-93CF-92449C4BBAA9} = {C40883CD-366D-4534-8B58-3EA0D13136DF} + {6C320AD9-F380-4F8B-85F9-0689F88766EC} = {C40883CD-366D-4534-8B58-3EA0D13136DF} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A855CFDC-9BEE-43A9-A3EA-4C4624A747DB} EndGlobalSection EndGlobal diff --git a/RuntimePortable.sln b/RuntimePortable.sln deleted file mode 100644 index 89fc0c66d..000000000 --- a/RuntimePortable.sln +++ /dev/null @@ -1,66 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A9836F9E-6DB3-4D9F-ADCA-CF42D8C8BA93}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C40883CD-366D-4534-8B58-3EA0D13136DF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.TestCommon", "test\Microsoft.TestCommon\Microsoft.TestCommon.csproj", "{FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Http.Formatting.NetCore", "src\System.Net.Http.Formatting.NetCore\System.Net.Http.Formatting.NetCore.csproj", "{C7060639-719B-4BD2-8A37-2F146B5A0668}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Http.Formatting.NetCore.Test", "test\System.Net.Http.Formatting.NetCore.Test\System.Net.Http.Formatting.NetCore.Test.csproj", "{8DA61DAC-FF7E-4CA1-93A0-6148DB66FD08}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Http.Formatting.NetStandard", "src\System.Net.Http.Formatting.NetStandard\System.Net.Http.Formatting.NetStandard.csproj", "{636CA76A-C85C-42E2-B4AA-88046279B3CA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Http.Formatting.NetStandard.Test", "test\System.Net.Http.Formatting.NetStandard.Test\System.Net.Http.Formatting.NetStandard.Test.csproj", "{DECB05DF-B33A-44A0-B5DE-B14A8CE0740F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - CodeAnalysis|Any CPU = CodeAnalysis|Any CPU - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU - {FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU - {FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0}.Release|Any CPU.Build.0 = Release|Any CPU - {C7060639-719B-4BD2-8A37-2F146B5A0668}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU - {C7060639-719B-4BD2-8A37-2F146B5A0668}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU - {C7060639-719B-4BD2-8A37-2F146B5A0668}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C7060639-719B-4BD2-8A37-2F146B5A0668}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C7060639-719B-4BD2-8A37-2F146B5A0668}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C7060639-719B-4BD2-8A37-2F146B5A0668}.Release|Any CPU.Build.0 = Release|Any CPU - {8DA61DAC-FF7E-4CA1-93A0-6148DB66FD08}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU - {8DA61DAC-FF7E-4CA1-93A0-6148DB66FD08}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU - {8DA61DAC-FF7E-4CA1-93A0-6148DB66FD08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8DA61DAC-FF7E-4CA1-93A0-6148DB66FD08}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8DA61DAC-FF7E-4CA1-93A0-6148DB66FD08}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8DA61DAC-FF7E-4CA1-93A0-6148DB66FD08}.Release|Any CPU.Build.0 = Release|Any CPU - {636CA76A-C85C-42E2-B4AA-88046279B3CA}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU - {636CA76A-C85C-42E2-B4AA-88046279B3CA}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU - {636CA76A-C85C-42E2-B4AA-88046279B3CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {636CA76A-C85C-42E2-B4AA-88046279B3CA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {636CA76A-C85C-42E2-B4AA-88046279B3CA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {636CA76A-C85C-42E2-B4AA-88046279B3CA}.Release|Any CPU.Build.0 = Release|Any CPU - {DECB05DF-B33A-44A0-B5DE-B14A8CE0740F}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU - {DECB05DF-B33A-44A0-B5DE-B14A8CE0740F}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU - {DECB05DF-B33A-44A0-B5DE-B14A8CE0740F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DECB05DF-B33A-44A0-B5DE-B14A8CE0740F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DECB05DF-B33A-44A0-B5DE-B14A8CE0740F}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {DECB05DF-B33A-44A0-B5DE-B14A8CE0740F}.Release|Any CPU.Build.0 = Debug|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {C7060639-719B-4BD2-8A37-2F146B5A0668} = {A9836F9E-6DB3-4D9F-ADCA-CF42D8C8BA93} - {FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0} = {C40883CD-366D-4534-8B58-3EA0D13136DF} - {8DA61DAC-FF7E-4CA1-93A0-6148DB66FD08} = {C40883CD-366D-4534-8B58-3EA0D13136DF} - {636CA76A-C85C-42E2-B4AA-88046279B3CA} = {A9836F9E-6DB3-4D9F-ADCA-CF42D8C8BA93} - {DECB05DF-B33A-44A0-B5DE-B14A8CE0740F} = {C40883CD-366D-4534-8B58-3EA0D13136DF} - EndGlobalSection -EndGlobal diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..edbf5411a --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +## Reporting a Vulnerability + +Security issues and bugs should be reported privately to the Microsoft Security Response Center (MSRC), either by emailing secure@microsoft.com or via the portal at https://msrc.microsoft.com. +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your +original message. Further information, including the MSRC PGP key, can be found in the [MSRC Report an Issue FAQ](https://www.microsoft.com/en-us/msrc/faqs-report-an-issue). + +Please do not open issues for anything you think might have a security implication. \ No newline at end of file diff --git a/Tools.sln b/Tools.sln index 968050b6c..aae4eaa5a 100644 --- a/Tools.sln +++ b/Tools.sln @@ -1,8 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.27016.1 +MinimumVisualStudioVersion = 15.0 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Web.FxCop", "tools\src\Microsoft.Web.FxCop\Microsoft.Web.FxCop.csproj", "{F439D4E6-3FAC-4C30-9585-6D258133A2BF}" EndProject Global @@ -19,4 +19,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F8728741-0321-4EF6-9359-7DF2DCE6E99E} + EndGlobalSection EndGlobal diff --git a/azure-pipelines-public.yml b/azure-pipelines-public.yml new file mode 100644 index 000000000..7089d6acb --- /dev/null +++ b/azure-pipelines-public.yml @@ -0,0 +1,33 @@ +parameters: + # Test only the Release build by default. +- name: ReleaseBuildTarget + displayName: 'Build which target for Release?' + type: string + values: [ Build, Integration, UnitTest ] + default: UnitTest +- name: OtherBuildTarget + displayName: 'Build which target for Debug/CodeAnalysis?' + type: string + values: [ Build, Integration, UnitTest ] + default: Build + +variables: +- name: DOTNET_CLI_TELEMETRY_OPTOUT + value: 1 +- name: DOTNET_NOLOGO + value: 1 + # Run CodeQL3000 tasks in a separate internal pipeline; not needed here. +- name: Codeql.SkipTaskAutoInjection + value: true + +trigger: [main] +pr: ['*'] + +stages: +- stage: build + displayName: Build + jobs: + - template: /eng/templates/default-build.yml + parameters: + ReleaseBuildTarget: ${{ parameters.ReleaseBuildTarget }} + OtherBuildTarget: ${{ parameters.OtherBuildTarget }} diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000..6f110512d --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,53 @@ +parameters: + # Test only the Release build by default. +- name: ReleaseBuildTarget + displayName: 'Build which target for Release?' + type: string + values: [ Build, Integration, UnitTest ] + default: Build +- name: OtherBuildTarget + displayName: 'Build which target for Debug/CodeAnalysis?' + type: string + values: [ Build, Integration, UnitTest ] + default: Build + +variables: +- name: DOTNET_CLI_TELEMETRY_OPTOUT + value: 1 +- name: DOTNET_NOLOGO + value: 1 + # Run CodeQL3000 tasks in a separate internal pipeline; not needed here. +- name: Codeql.SkipTaskAutoInjection + value: true + +trigger: [main] +pr: ['*'] + +resources: + repositories: + # Repo: 1ESPipelineTemplates/1ESPipelineTemplates + - repository: 1esPipelines + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines + parameters: + sdl: + policheck: + enabled: true + tsa: + enabled: true + pool: + name: NetCore1ESPool-Svc-Internal + image: 1es-windows-2019 + os: windows + stages: + - stage: build + displayName: Build + jobs: + - template: /eng/templates/default-build.yml@self + parameters: + ReleaseBuildTarget: ${{ parameters.ReleaseBuildTarget }} + OtherBuildTarget: ${{ parameters.OtherBuildTarget }} diff --git a/build.cmd b/build.cmd index 4afef96e7..5802269fe 100644 --- a/build.cmd +++ b/build.cmd @@ -1,41 +1,104 @@ @echo off -pushd %~dp0 setlocal -if exist bin goto build +if exist bin goto Build mkdir bin :Build -REM Find the most recent 32bit MSBuild.exe on the system. Require v12.0 (installed with VS2013) or later since .NET 4.0 -REM is not supported. Also handle x86 operating systems, where %ProgramFiles(x86)% is not defined. Always quote the -REM %MSBuild% value when setting the variable and never quote %MSBuild% references. -set MSBuild="%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe" -if not exist %MSBuild% @set MSBuild="%ProgramFiles%\MSBuild\14.0\Bin\MSBuild.exe" -if not exist %MSBuild% @set MSBuild="%ProgramFiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe" -if not exist %MSBuild% @set MSBuild="%ProgramFiles%\MSBuild\12.0\Bin\MSBuild.exe" +REM Require VS2019 (v16.0) on the system. Use `vswhere` for the search because it can find all VS installations. +set vswhere="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +if not exist %vswhere% ( + set vswhere="%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" +) +if not exist %vswhere% ( + REM vswhere.exe not in normal locations; check the Path. + for %%X in (vswhere.exe) do ( + set vswhere="%%~$PATH:X" + ) +) +if not exist %vswhere% ( + echo Could not find vswhere.exe. Please run this from a Visual Studio developer prompt. + goto BuildFail +) + +set InstallDir= +for /f "usebackq tokens=*" %%i in (`%vswhere% -version 16 -latest -prerelease -products * ^ + -requires Microsoft.Net.Component.4.5.TargetingPack ^ + -requires Microsoft.Net.Component.4.5.2.TargetingPack ^ + -requires Microsoft.Net.Component.4.6.2.TargetingPack ^ + -property installationPath`) do ( + set "InstallDir=%%i" +) + +if not DEFINED InstallDir ( + echo "Could not find a VS2019 installation with the necessary components (targeting packs for v4.5, v4.5.2, and v4.6.2)." + echo Please install VS2019 or the missing components. + goto BuildFail +) + +REM Find a 64bit MSBuild and add it to path. Require v17.4 or later due to our .NET SDK choice. +REM Check for VS2022 first. +set InstallDir= +for /f "usebackq tokens=*" %%i in (`%vswhere% -version 17.4 -latest -prerelease -products * ^ + -requires Microsoft.Component.MSBuild ^ + -property installationPath`) do ( + set "InstallDir=%%i" +) + +if DEFINED InstallDir ( + REM Add MSBuild to the path. + set "PATH=%InstallDir%\MSBuild\Current\Bin;%PATH%" + goto FoundMSBuild +) + +REM Otherwise find or install an xcopy-able MSBuild. +echo "Could not find a VS2022 installation with the necessary components (MSBuild). Falling back..." + +set "MSBuildVersion=17.4.1" +set "Command=[System.Threading.Thread]::CurrentThread.CurrentCulture = ''" +set "Command=%Command%; [System.Threading.Thread]::CurrentThread.CurrentUICulture = ''" +set "Command=%Command%; try { & '%~dp0eng\GetXCopyMSBuild.ps1' %MSBuildVersion%; exit $LASTEXITCODE }" +set "Command=%Command% catch { write-host $_; exit 1 }" +PowerShell -NoProfile -NoLogo -ExecutionPolicy Bypass -Command "%Command%" +if %ERRORLEVEL% neq 0 goto BuildFail +REM Add MSBuild to the path. +set "PATH=%~dp0.msbuild\%MSBuildVersion%\tools\MSBuild\Current\Bin;%PATH%" + +:FoundMSBuild +REM Configure NuGet operations to work w/in this repo i.e. do not pollute system packages folder. +REM Note this causes two copies of packages restored using packages.config to land in this folder e.g. +REM StyleCpy.5.0.0/ and stylecop/5.0.0/. +set "NUGET_PACKAGES=%~dp0packages" + +REM Are we running in a local dev environment (not on CI)? +if DEFINED CI (set Desktop=false) else if DEFINED TEAMCITY_VERSION (set Desktop=false) else (set Desktop=true) + +pushd %~dp0 if "%1" == "" goto BuildDefaults -%MSBuild% Runtime.msbuild /m /nr:false /t:%* /p:Platform="Any CPU" /p:Desktop=true /v:M /fl /flp:LogFile=bin\msbuild.log;Verbosity=Normal +MSBuild "%~dp0Runtime.msbuild" /m /nr:false /p:Platform="Any CPU" /p:Desktop=%Desktop% /v:M ^ + /fl /fileLoggerParameters:LogFile=bin\msbuild.log;Verbosity=Normal /consoleLoggerParameters:Summary /t:%* if %ERRORLEVEL% neq 0 goto BuildFail goto BuildSuccess :BuildDefaults -%MSBuild% Runtime.msbuild /m /nr:false /p:Platform="Any CPU" /p:Desktop=true /v:M /fl /flp:LogFile=bin\msbuild.log;Verbosity=detailed +MSBuild "%~dp0Runtime.msbuild" /m /nr:false /p:Platform="Any CPU" /p:Desktop=%Desktop% /v:M ^ + /fl /fileLoggerParameters:LogFile=bin\msbuild.log;Verbosity=Normal /consoleLoggerParameters:Summary if %ERRORLEVEL% neq 0 goto BuildFail goto BuildSuccess :BuildFail echo. echo *** BUILD FAILED *** -goto End +popd +endlocal +exit /B 999 :BuildSuccess echo. echo **** BUILD SUCCESSFUL *** -goto end - -:End popd endlocal +exit /B 0 diff --git a/eng/GetXCopyMSBuild.ps1 b/eng/GetXCopyMSBuild.ps1 new file mode 100644 index 000000000..667839289 --- /dev/null +++ b/eng/GetXCopyMSBuild.ps1 @@ -0,0 +1,43 @@ +# Lifted from https://github.com/dotnet/arcade/blob/main/eng/common/tools.ps1 + +[CmdletBinding(DefaultParameterSetName='Groups')] +param( + [string]$Version = '17.4.1' +) + +Set-StrictMode -Version 2 +$ErrorActionPreference = 'Stop' + +function Create-Directory ([string[]] $path) { + New-Item -Path $path -Force -ItemType 'Directory' | Out-Null +} + +function Unzip([string]$zipfile, [string]$outpath) { + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath) +} + +function InitializeXCopyMSBuild([string]$packageVersion, [bool]$install, [string]$ToolsDir) { + $packageName = 'RoslynTools.MSBuild' + $packageDir = Join-Path $ToolsDir $packageVersion + $packagePath = Join-Path $packageDir "$packageName.$packageVersion.nupkg" + + if (!(Test-Path $packageDir)) { + if (!$install) { + return $null + } + + Create-Directory $packageDir + + Write-Host "Downloading $packageName $packageVersion" + $ProgressPreference = 'SilentlyContinue' # Don't display the console progress UI - it's a huge perf hit + Invoke-WebRequest "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/flat2/$packageName/$packageVersion/$packageName.$packageVersion.nupkg" -OutFile $packagePath + + Unzip $packagePath $packageDir + } + + return Join-Path $packageDir 'tools' +} + +$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\') +InitializeXCopyMSBuild -packageVersion $Version -install $true -ToolsDir (join-path $RepoRoot .msbuild) diff --git a/eng/templates/default-build.yml b/eng/templates/default-build.yml new file mode 100644 index 000000000..7000a4dad --- /dev/null +++ b/eng/templates/default-build.yml @@ -0,0 +1,95 @@ +parameters: + ReleaseBuildTarget: '' + OtherBuildTarget: '' + +jobs: +- job: build + displayName: Build + ${{ if eq(variables['System.TeamProject'], 'public') }}: + pool: + name: NetCore-Svc-Public + demands: ImageOverride -equals windows.vs2019.amd64.open + timeoutInMinutes: 30 + + strategy: + matrix: + Release: + _BuildTarget: ${{ parameters.ReleaseBuildTarget }} + _Configuration: Release + _StyleCopEnabled: true + # Do CG work only in internal pipelines. + skipComponentGovernanceDetection: ${{ eq(variables['System.TeamProject'], 'public') }} + Debug: + _BuildTarget: ${{ parameters.OtherBuildTarget }} + _Configuration: Debug + _StyleCopEnabled: false + # Do not redo CG work. Configuration changes in this part of the matrix are not relevant to CG. + skipComponentGovernanceDetection: true + CodeAnalysis: + _BuildTarget: ${{ parameters.OtherBuildTarget }} + _Configuration: CodeAnalysis + _StyleCopEnabled: false + # Do not redo CG work. Configuration changes in this part of the matrix are not relevant to CG. + skipComponentGovernanceDetection: true + + steps: + - checkout: self + clean: true + displayName: Checkout + + - task: UseDotNet@2 + displayName: Get .NET SDK + inputs: + useGlobalJson: true + - task: UseDotNet@2 + displayName: Get .NET 2.1 runtime + inputs: + packageType: runtime + version: '2.1.x' + + - script: .\build.cmd EnableSkipStrongNames + displayName: Enable SkipStrongNames + - script: .\build.cmd $(_BuildTarget) ^ + /binaryLogger:artifacts/msbuild.binlog /p:Configuration=$(_Configuration) /p:StyleCopEnabled=$(_StyleCopEnabled) ^ + /fileLoggerParameters:LogFile=artifacts/msbuild.log;Summary;Verbosity=minimal + displayName: Build + + - ${{ if eq(variables['System.TeamProject'], 'public') }}: + - task: PublishBuildArtifacts@1 + displayName: Upload test results + condition: and(always(), ne(variables._BuildTarget, 'Build')) + continueOnError: true + inputs: + pathtoPublish: ./bin/$(_Configuration)/Test/TestResults/ + artifactName: $(_Configuration) Test Results $(System.JobId) + artifactType: Container + parallel: true + - task: PublishTestResults@2 + condition: and(always(), ne(variables._BuildTarget, 'Build')) + continueOnError: true + displayName: Publish test results + inputs: + mergeTestResults: true + searchFolder: ./bin/$(_Configuration)/Test/TestResults/ + testResultsFiles: '*.xml' + testRunner: xUnit + testRunTitle: $(_Configuration) + - task: PublishBuildArtifacts@1 + displayName: Upload logs + condition: always() + continueOnError: true + inputs: + pathtoPublish: ./artifacts/ + artifactName: $(_Configuration) Logs $(System.JobId) + artifactType: Container + parallel: true + - ${{ if eq(variables['System.TeamProject'], 'internal') }}: + - task: 1ES.PublishPipelineArtifact@1 + inputs: + condition: and(always(), ne(variables._BuildTarget, 'Build')) + path: ./bin/$(_Configuration)/Test/TestResults/ + artifact: $(_Configuration) Test Results $(System.JobId) + - task: 1ES.PublishPipelineArtifact@1 + inputs: + path: ./artifacts/ + artifact: $(_Configuration) Logs $(System.JobId) diff --git a/es-metadata.yml b/es-metadata.yml new file mode 100644 index 000000000..9061e1181 --- /dev/null +++ b/es-metadata.yml @@ -0,0 +1,8 @@ +schemaVersion: 0.0.1 +isProduction: true +accountableOwners: + service: 4db45fa9-fb0f-43ce-b523-ad1da773dfbc +routing: + defaultAreaPath: + org: devdiv + path: DevDiv\ASP.NET Core diff --git a/global.json b/global.json index f992be3d4..0f75e8a6f 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,6 @@ { "sdk": { - "version": "1.0.4" + "version": "6.0.405", + "rollForward": "major" } -} \ No newline at end of file +} diff --git a/packages/repositories.config b/packages/repositories.config index 8bede8eeb..18d08a3de 100644 --- a/packages/repositories.config +++ b/packages/repositories.config @@ -3,7 +3,6 @@ - @@ -17,11 +16,9 @@ - - diff --git a/src/CodeAnalysisDictionary.xml b/src/CodeAnalysisDictionary.xml index fdd4e0ea7..26ab4a8af 100644 --- a/src/CodeAnalysisDictionary.xml +++ b/src/CodeAnalysisDictionary.xml @@ -55,6 +55,13 @@ ModelName BSON Untyped + Behavior + Callback + Canceled + Color + Fallback + Markup + Preflight WebPage diff --git a/src/Common/CollectionExtensions.cs b/src/Common/CollectionExtensions.cs index c89d4ad98..bfd1eb61d 100644 --- a/src/Common/CollectionExtensions.cs +++ b/src/Common/CollectionExtensions.cs @@ -27,7 +27,7 @@ public static T[] AppendAndReallocate(this T[] array, T value) } /// - /// Return the enumerable as an Array, copying if required. Optimized for common case where it is an Array. + /// Return the enumerable as an Array, copying if required. Optimized for common case where it is an Array. /// Avoid mutating the return value. /// public static T[] AsArray(this IEnumerable values) @@ -43,7 +43,7 @@ public static T[] AsArray(this IEnumerable values) } /// - /// Return the enumerable as a Collection of T, copying if required. Optimized for the common case where it is + /// Return the enumerable as a Collection of T, copying if required. Optimized for the common case where it is /// a Collection of T and avoiding a copy if it implements IList of T. Avoid mutating the return value. /// public static Collection AsCollection(this IEnumerable enumerable) @@ -78,9 +78,9 @@ public static IList AsIList(this IEnumerable enumerable) } return new List(enumerable); } - + /// - /// Return the enumerable as a List of T, copying if required. Optimized for common case where it is an List of T + /// Return the enumerable as a List of T, copying if required. Optimized for common case where it is an List of T /// or a ListWrapperCollection of T. Avoid mutating the return value. /// public static List AsList(this IEnumerable enumerable) diff --git a/src/Common/CommonWebApiResources.Designer.cs b/src/Common/CommonWebApiResources.Designer.cs index 4ceb3f115..6e1e476d6 100644 --- a/src/Common/CommonWebApiResources.Designer.cs +++ b/src/Common/CommonWebApiResources.Designer.cs @@ -24,15 +24,15 @@ namespace System.Web.Http.Properties { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class CommonWebApiResources { - + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal CommonWebApiResources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -40,7 +40,7 @@ internal CommonWebApiResources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { -#if NETFX_CORE +#if NETSTANDARD1_3 var assembly = typeof(CommonWebApiResources).GetTypeInfo().Assembly; #else var assembly = typeof(CommonWebApiResources).Assembly; @@ -59,7 +59,7 @@ internal CommonWebApiResources() { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -73,7 +73,7 @@ internal CommonWebApiResources() { resourceCulture = value; } } - + /// /// Looks up a localized string similar to Relative URI values are not supported: '{0}'. The URI must be absolute.. /// @@ -82,7 +82,7 @@ internal static string ArgumentInvalidAbsoluteUri { return ResourceManager.GetString("ArgumentInvalidAbsoluteUri", resourceCulture); } } - + /// /// Looks up a localized string similar to Unsupported URI scheme: '{0}'. The URI scheme must be either '{1}' or '{2}'.. /// @@ -91,7 +91,7 @@ internal static string ArgumentInvalidHttpUriScheme { return ResourceManager.GetString("ArgumentInvalidHttpUriScheme", resourceCulture); } } - + /// /// Looks up a localized string similar to Value must be greater than or equal to {0}.. /// @@ -100,7 +100,7 @@ internal static string ArgumentMustBeGreaterThanOrEqualTo { return ResourceManager.GetString("ArgumentMustBeGreaterThanOrEqualTo", resourceCulture); } } - + /// /// Looks up a localized string similar to Value must be less than or equal to {0}.. /// @@ -109,7 +109,7 @@ internal static string ArgumentMustBeLessThanOrEqualTo { return ResourceManager.GetString("ArgumentMustBeLessThanOrEqualTo", resourceCulture); } } - + /// /// Looks up a localized string similar to The argument '{0}' is null or empty.. /// @@ -118,7 +118,7 @@ internal static string ArgumentNullOrEmpty { return ResourceManager.GetString("ArgumentNullOrEmpty", resourceCulture); } } - + /// /// Looks up a localized string similar to URI must not contain a query component or a fragment identifier.. /// @@ -127,7 +127,7 @@ internal static string ArgumentUriHasQueryOrFragment { return ResourceManager.GetString("ArgumentUriHasQueryOrFragment", resourceCulture); } } - + /// /// Looks up a localized string similar to The value of argument '{0}' ({1}) is invalid for Enum type '{2}'.. /// diff --git a/src/Common/Error.cs b/src/Common/Error.cs index 0e8c83465..85449c142 100644 --- a/src/Common/Error.cs +++ b/src/Common/Error.cs @@ -74,7 +74,7 @@ internal static ArgumentException ArgumentUriNotAbsolute(string parameterName, U } /// - /// Creates an with a message saying that the argument must be an absolute URI + /// Creates an with a message saying that the argument must be an absolute URI /// without a query or fragment identifier and then logs it with . /// /// The name of the parameter that caused the current exception. @@ -225,11 +225,7 @@ internal static OperationCanceledException OperationCanceled(string messageForma /// The logged . internal static ArgumentException InvalidEnumArgument(string parameterName, int invalidValue, Type enumClass) { -#if NETFX_CORE - return new ArgumentException(Error.Format(CommonWebApiResources.InvalidEnumArgument, parameterName, invalidValue, enumClass.Name), parameterName); -#else return new InvalidEnumArgumentException(parameterName, invalidValue, enumClass); -#endif } /// @@ -265,5 +261,24 @@ internal static NotSupportedException NotSupported(string messageFormat, params { return new NotSupportedException(Error.Format(messageFormat, messageArgs)); } + +#if NETSTANDARD1_3 // InvalidEnumArgumentException not available in netstandard1.3. + internal class InvalidEnumArgumentException : ArgumentException + { + public InvalidEnumArgumentException() : this(null) + { } + + public InvalidEnumArgumentException(string message) : base(message) + { } + + public InvalidEnumArgumentException(string message, Exception innerException) : base(message, innerException) + { } + + public InvalidEnumArgumentException(string argumentName, int invalidValue, Type enumClass) : base( + Error.Format(CommonWebApiResources.InvalidEnumArgument, argumentName, invalidValue, enumClass.Name), + argumentName) + { } + } +#endif } } diff --git a/src/Common/UriQueryUtility.cs b/src/Common/UriQueryUtility.cs deleted file mode 100644 index 53675e11a..000000000 --- a/src/Common/UriQueryUtility.cs +++ /dev/null @@ -1,278 +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. - -using System.Diagnostics.Contracts; -using System.Net; -using System.Text; - -namespace System.Web.Http -{ - /// - /// Helpers for encoding, decoding, and parsing URI query components. In .Net 4.5 - /// please use the WebUtility class. - /// - internal static class UriQueryUtility - { - public static string UrlEncode(string str) - { - if (str == null) - { - return null; - } - -#if NETFX_CORE - return WebUtility.UrlEncode(str); -#else - byte[] bytes = Encoding.UTF8.GetBytes(str); - return Encoding.ASCII.GetString(UrlEncode(bytes, 0, bytes.Length, alwaysCreateNewReturnValue: false)); -#endif - } - - public static string UrlDecode(string str) - { - if (str == null) - { - return null; - } - -#if NETFX_CORE - return WebUtility.UrlDecode(str); -#else - return UrlDecodeInternal(str, Encoding.UTF8); -#endif - } - -#if !NETFX_CORE - private static byte[] UrlEncode(byte[] bytes, int offset, int count, bool alwaysCreateNewReturnValue) - { - byte[] encoded = UrlEncode(bytes, offset, count); - - return (alwaysCreateNewReturnValue && (encoded != null) && (encoded == bytes)) - ? (byte[])encoded.Clone() - : encoded; - } - - private static byte[] UrlEncode(byte[] bytes, int offset, int count) - { - if (!ValidateUrlEncodingParameters(bytes, offset, count)) - { - return null; - } - - int cSpaces = 0; - int cUnsafe = 0; - - // count them first - for (int i = 0; i < count; i++) - { - char ch = (char)bytes[offset + i]; - - if (ch == ' ') - cSpaces++; - else if (!IsUrlSafeChar(ch)) - cUnsafe++; - } - - // nothing to expand? - if (cSpaces == 0 && cUnsafe == 0) - return bytes; - - // expand not 'safe' characters into %XX, spaces to +s - byte[] expandedBytes = new byte[count + cUnsafe * 2]; - int pos = 0; - - for (int i = 0; i < count; i++) - { - byte b = bytes[offset + i]; - char ch = (char)b; - - if (IsUrlSafeChar(ch)) - { - expandedBytes[pos++] = b; - } - else if (ch == ' ') - { - expandedBytes[pos++] = (byte)'+'; - } - else - { - expandedBytes[pos++] = (byte)'%'; - expandedBytes[pos++] = (byte)IntToHex((b >> 4) & 0xf); - expandedBytes[pos++] = (byte)IntToHex(b & 0x0f); - } - } - - return expandedBytes; - } - - private static string UrlDecodeInternal(string value, Encoding encoding) - { - if (value == null) - { - return null; - } - - int count = value.Length; - UrlDecoder helper = new UrlDecoder(count, encoding); - - // go through the string's chars collapsing %XX and %uXXXX and - // appending each char as char, with exception of %XX constructs - // that are appended as bytes - - for (int pos = 0; pos < count; pos++) - { - char ch = value[pos]; - - if (ch == '+') - { - ch = ' '; - } - else if (ch == '%' && pos < count - 2) - { - int h1 = HexToInt(value[pos + 1]); - int h2 = HexToInt(value[pos + 2]); - - if (h1 >= 0 && h2 >= 0) - { - // valid 2 hex chars - byte b = (byte)((h1 << 4) | h2); - pos += 2; - - // don't add as char - helper.AddByte(b); - continue; - } - } - - if ((ch & 0xFF80) == 0) - helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode - else - helper.AddChar(ch); - } - - return helper.GetString(); - } - - private static int HexToInt(char h) - { - return (h >= '0' && h <= '9') ? h - '0' : - (h >= 'a' && h <= 'f') ? h - 'a' + 10 : - (h >= 'A' && h <= 'F') ? h - 'A' + 10 : - -1; - } - - private static char IntToHex(int n) - { - Contract.Assert(n < 0x10); - - if (n <= 9) - return (char)(n + (int)'0'); - else - return (char)(n - 10 + (int)'a'); - } - - // Set of safe chars, from RFC 1738.4 minus '+' - private static bool IsUrlSafeChar(char ch) - { - if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9') - return true; - - switch (ch) - { - case '-': - case '_': - case '.': - case '!': - case '*': - case '(': - case ')': - return true; - } - - return false; - } - - private static bool ValidateUrlEncodingParameters(byte[] bytes, int offset, int count) - { - if (bytes == null && count == 0) - return false; - if (bytes == null) - { - throw Error.ArgumentNull("bytes"); - } - if (offset < 0 || offset > bytes.Length) - { - throw new ArgumentOutOfRangeException("offset"); - } - if (count < 0 || offset + count > bytes.Length) - { - throw new ArgumentOutOfRangeException("count"); - } - - return true; - } - - // Internal class to facilitate URL decoding -- keeps char buffer and byte buffer, allows appending of either chars or bytes - private class UrlDecoder - { - private int _bufferSize; - - // Accumulate characters in a special array - private int _numChars; - private char[] _charBuffer; - - // Accumulate bytes for decoding into characters in a special array - private int _numBytes; - private byte[] _byteBuffer; - - // Encoding to convert chars to bytes - private Encoding _encoding; - - private void FlushBytes() - { - if (_numBytes > 0) - { - _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars); - _numBytes = 0; - } - } - - internal UrlDecoder(int bufferSize, Encoding encoding) - { - _bufferSize = bufferSize; - _encoding = encoding; - - _charBuffer = new char[bufferSize]; - // byte buffer created on demand - } - - internal void AddChar(char ch) - { - if (_numBytes > 0) - FlushBytes(); - - _charBuffer[_numChars++] = ch; - } - - internal void AddByte(byte b) - { - if (_byteBuffer == null) - _byteBuffer = new byte[_bufferSize]; - - _byteBuffer[_numBytes++] = b; - } - - internal String GetString() - { - if (_numBytes > 0) - FlushBytes(); - - if (_numChars > 0) - return new String(_charBuffer, 0, _numChars); - else - return String.Empty; - } - } -#endif - } -} \ No newline at end of file diff --git a/src/CommonAssemblyInfo.cs b/src/CommonAssemblyInfo.cs index 62d86c357..de4e5d379 100644 --- a/src/CommonAssemblyInfo.cs +++ b/src/CommonAssemblyInfo.cs @@ -19,17 +19,22 @@ [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyMetadata("Serviceable", "True")] -// =========================================================================== -// DO NOT EDIT OR REMOVE ANYTHING BELOW THIS COMMENT. -// Version numbers are automatically generated based on regular expressions. -// =========================================================================== +// =================================================================================== +// TAKE CARE WHEN EDITING OR REMOVING ANYTHING BELOW THIS COMMENT. +// BUILD_GENERATED_VERSION will be set in any CI build. Versions below are not used. +// =================================================================================== -#if ASPNETMVC && ASPNETWEBPAGES -#error Runtime projects cannot define both ASPNETMVC and ASPNETWEBPAGES +#if (ASPNETMVC && (ASPNETWEBPAGES || ASPNETFACEBOOK || ASPNETHTTPFORMATTING)) || (ASPNETWEBPAGES && (ASPNETFACEBOOK || ASPNETHTTPFORMATTING)) || (ASPNETFACEBOOK && ASPNETHTTPFORMATTING) +#error Runtime projects cannot define more than one of ASPNETMVC, ASPNETWEBPAGES, ASPNETFACEBOOK, or ASPNETHTTPFORMATTING +#elif ASPNETHTTPFORMATTING +#if !BUILD_GENERATED_VERSION +[assembly: AssemblyVersion("6.0.0.0")] // ASPNETHTTPFORMATTING +[assembly: AssemblyFileVersion("6.0.0.0")] // ASPNETHTTPFORMATTING +#endif #elif ASPNETMVC #if !BUILD_GENERATED_VERSION -[assembly: AssemblyVersion("5.2.4.0")] // ASPNETMVC -[assembly: AssemblyFileVersion("5.2.4.0")] // ASPNETMVC +[assembly: AssemblyVersion("5.3.0.0")] // ASPNETMVC +[assembly: AssemblyFileVersion("5.3.0.0")] // ASPNETMVC #endif [assembly: AssemblyProduct("Microsoft ASP.NET MVC")] #elif ASPNETWEBPAGES @@ -45,5 +50,5 @@ #endif [assembly: AssemblyProduct("Microsoft ASP.NET Facebook")] #else -#error Runtime projects must define either ASPNETMVC or ASPNETWEBPAGES +#error Runtime projects must define ASPNETMVC, ASPNETWEBPAGES or ASPNETFACEBOOK #endif diff --git a/src/CommonAssemblyInfo.vb b/src/CommonAssemblyInfo.vb index 613b66814..d5dac6315 100644 --- a/src/CommonAssemblyInfo.vb +++ b/src/CommonAssemblyInfo.vb @@ -20,6 +20,6 @@ Imports System.Runtime.InteropServices ' Version numbers are automatically generated based on regular expressions. ' =========================================================================== - 'ASPNETMVC - 'ASPNETMVC + 'ASPNETMVC + 'ASPNETMVC \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 000000000..6785fd164 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + true + false + v4.5 + + diff --git a/src/Microsoft.AspNet.Facebook/Microsoft.AspNet.Facebook.csproj b/src/Microsoft.AspNet.Facebook/Microsoft.AspNet.Facebook.csproj index a25890bc8..12642c354 100644 --- a/src/Microsoft.AspNet.Facebook/Microsoft.AspNet.Facebook.csproj +++ b/src/Microsoft.AspNet.Facebook/Microsoft.AspNet.Facebook.csproj @@ -26,9 +26,10 @@ False ..\..\packages\Facebook.6.4.2\lib\net45\Facebook.dll - + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + False diff --git a/src/Microsoft.AspNet.Facebook/packages.config b/src/Microsoft.AspNet.Facebook/packages.config index 613e222f9..102ce84aa 100644 --- a/src/Microsoft.AspNet.Facebook/packages.config +++ b/src/Microsoft.AspNet.Facebook/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file diff --git a/src/Strict.ruleset b/src/Strict.ruleset index 5a2a69ba9..a0c61fcb5 100644 --- a/src/Strict.ruleset +++ b/src/Strict.ruleset @@ -6,5 +6,7 @@ + + \ No newline at end of file diff --git a/src/System.Net.Http.Formatting.NetCore/GlobalSuppressions.cs b/src/System.Net.Http.Formatting.NetCore/GlobalSuppressions.cs deleted file mode 100644 index 778d614cd..000000000 --- a/src/System.Net.Http.Formatting.NetCore/GlobalSuppressions.cs +++ /dev/null @@ -1,10 +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. - -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")] -[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "System.Net.Http.Headers", Justification = "We follow the layout of System.Net.Http.")] -[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "System.Net.Http.Handlers", Justification = "Handlers provide an extensibility hook which we want to keep in a separate namespace.")] -[assembly: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant", Scope = "module", Target = "system.net.http.formatting.dll", Justification = "CLSCompliant is not applicable to the portable version of the assembly.")] -[assembly: SuppressMessage("Microsoft.Web.FxCop", "MW1000:UnusedResourceUsageRule", Scope = "module", Target = "system.net.http.formatting.dll", Justification = "The resources are only used in the non-portable version of the assembly.")] diff --git a/src/System.Net.Http.Formatting.NetCore/Internal/ConcurrentDictionary.cs b/src/System.Net.Http.Formatting.NetCore/Internal/ConcurrentDictionary.cs deleted file mode 100644 index 3df580802..000000000 --- a/src/System.Net.Http.Formatting.NetCore/Internal/ConcurrentDictionary.cs +++ /dev/null @@ -1,192 +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. - -#if NETFX_CORE // This file should only be included by the NetCore version of the formatting project, but adding a guard here just in case. -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace System.Net.Http.Internal -{ - // TODO: Remove this class after BCL makes their portable library version. - internal sealed class ConcurrentDictionary : IDictionary - { - private Dictionary _dictionary = new Dictionary(); - private object _lock = new object(); - - public ICollection Keys - { - get - { - throw new NotImplementedException(); - } - } - - public ICollection Values - { - get - { - throw new NotImplementedException(); - } - } - - public int Count - { - get - { - throw new NotImplementedException(); - } - } - - public bool IsReadOnly - { - get - { - return ((IDictionary)_dictionary).IsReadOnly; - } - } - - public TValue this[TKey key] - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public void Add(TKey key, TValue value) - { - throw new NotImplementedException(); - } - - public bool ContainsKey(TKey key) - { - lock (_lock) - { - return _dictionary.ContainsKey(key); - } - } - - public bool Remove(TKey key) - { - throw new NotImplementedException(); - } - - public bool TryGetValue(TKey key, out TValue value) - { - lock (_lock) - { - return _dictionary.TryGetValue(key, out value); - } - } - - public void Add(KeyValuePair item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(KeyValuePair item) - { - throw new NotImplementedException(); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public bool Remove(KeyValuePair item) - { - throw new NotImplementedException(); - } - - public IEnumerator> GetEnumerator() - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - // ConcurrentDictionary members - public bool TryRemove(TKey key, out TValue removedValue) - { - lock (_lock) - { - if (_dictionary.TryGetValue(key, out removedValue)) - { - return _dictionary.Remove(key); - } - - return false; - } - } - - public TValue GetOrAdd(TKey key, Func addValueFactory) - { - lock (_lock) - { - TValue value; - - if (!_dictionary.TryGetValue(key, out value)) - { - value = addValueFactory.Invoke(key); - _dictionary.Add(key, value); - } - - return value; - } - } - - public bool TryAdd(TKey key, TValue value) - { - lock (_lock) - { - if (_dictionary.ContainsKey(key)) - { - return false; - } - - _dictionary.Add(key, value); - return true; - } - } - - public TValue AddOrUpdate(TKey key, TValue addValue, Func updateValueFactory) - { - lock (_lock) - { - TValue value; - - // update - if (_dictionary.TryGetValue(key, out value)) - { - value = updateValueFactory.Invoke(key, value); - _dictionary[key] = value; - return value; - } - - // add - _dictionary.Add(key, addValue); - return addValue; - } - } - } -} -#endif \ No newline at end of file diff --git a/src/System.Net.Http.Formatting.NetCore/System.Net.Http.Formatting.NetCore.csproj b/src/System.Net.Http.Formatting.NetCore/System.Net.Http.Formatting.NetCore.csproj deleted file mode 100644 index c3d0a0827..000000000 --- a/src/System.Net.Http.Formatting.NetCore/System.Net.Http.Formatting.NetCore.csproj +++ /dev/null @@ -1,274 +0,0 @@ - - - - - {C7060639-719B-4BD2-8A37-2F146B5A0668} - Library - Properties - System.Net.Http - System.Net.Http.Formatting - $(OutputPath)NetCore\ - $(OutputPath)$(AssemblyName).xml - $(CodeAnalysis) - ..\Strict.ruleset - /assemblycomparemode:StrongNameIgnoringVersion - false - $(DefineConstants);NETFX_CORE;ASPNETMVC;NOT_CLS_COMPLIANT - Profile259 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 11.0 - 1591 - v4.5 - - - - Properties\CommonAssemblyInfo.cs - - - Common\Error.cs - - - Common\TaskHelpers.cs - - - Common\TaskHelpersExtensions.cs - - - Common\UriQueryUtility.cs - - - Common\CollectionExtensions.cs - - - Common\ListWrapperCollection.cs - - - FormattingUtilities.cs - - - Formatting\BaseJsonMediaTypeFormatter.cs - - - Formatting\BsonMediaTypeFormatter.cs - - - Formatting\DelegatingEnumerable.cs - - - Formatting\FormDataCollection.cs - - - Formatting\FormUrlEncodedJson.cs - - - Formatting\IFormatterLogger.cs - - - Formatting\JsonMediaTypeFormatter.cs - - - Formatting\MediaTypeConstants.cs - - - Formatting\MediaTypeFormatter.cs - - - Formatting\MediaTypeFormatterCollection.cs - - - Formatting\MediaTypeHeaderValueExtensions.cs - - - Formatting\MediaTypeHeaderValueRange.cs - - - Formatting\ParsedMediaTypeHeaderValue.cs - - - Formatting\Parsers\FormUrlEncodedParser.cs - - - Formatting\Parsers\HttpRequestHeaderParser.cs - - - Formatting\Parsers\HttpRequestLineParser.cs - - - Formatting\Parsers\HttpResponseHeaderParser.cs - - - Formatting\Parsers\HttpStatusLineParser.cs - - - Formatting\Parsers\InternetMessageFormatHeaderParser.cs - - - Formatting\Parsers\MimeMultipartBodyPartParser.cs - - - Formatting\Parsers\MimeMultipartParser.cs - - - Formatting\Parsers\ParserState.cs - - - Formatting\StringComparisonHelper.cs - - - Formatting\XmlMediaTypeFormatter.cs - - - HttpValueCollection.cs - - - UriExtensions.cs - - - - Handlers\HttpProgressEventArgs.cs - - - Handlers\ProgressContent.cs - - - Handlers\ProgressMessageHandler.cs - - - Handlers\ProgressStream.cs - - - HttpClientExtensions.cs - - - HttpClientFactory.cs - - - HttpContentExtensions.cs - - - HttpContentMessageExtensions.cs - - - HttpContentMultipartExtensions.cs - - - HttpHeaderExtensions.cs - - - HttpMessageContent.cs - - - HttpUnsortedHeaders.cs - - - HttpUnsortedRequest.cs - - - HttpUnsortedResponse.cs - - - Internal\AsyncResult.cs - - - Internal\DelegatingStream.cs - - - Internal\ReadOnlyStreamWithEncodingPreamble.cs - - - Internal\TypeExtensions.cs - - - MimeBodyPart.cs - - - MultipartFileData.cs - - - MultipartMemoryStreamProvider.cs - - - MultipartRelatedStreamProvider.cs - - - MultipartStreamProvider.cs - - - ObjectContent.cs - - - ObjectContentOfT.cs - - - PushStreamContent.cs - - - Properties\AssemblyInfo.cs - - - Properties\TransparentCommonAssemblyInfo.cs - True - True - Resources.resx - - - UnsupportedMediaTypeException.cs - - - - - - - Properties\CommonWebApiResources.Designer.cs - True - True - CommonWebApiResources.resx - - - - - Properties\CommonWebApiResources.resx - ResXFileCodeGenerator - CommonWebApiResources.Designer.cs - - - - - Properties\Resources.resx - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - - - CodeAnalysisDictionary.xml - - - - - - - - ..\..\packages\Newtonsoft.Json.6.0.4\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll - - - ..\..\packages\Microsoft.Net.Http.2.2.13\lib\portable-net40+sl4+win8+wp71\System.Net.Http.dll - - - ..\..\packages\Microsoft.Net.Http.2.2.13\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Extensions.dll - - - ..\..\packages\Microsoft.Net.Http.2.2.13\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Primitives.dll - - - - - - \ No newline at end of file diff --git a/src/System.Net.Http.Formatting.NetCore/packages.config b/src/System.Net.Http.Formatting.NetCore/packages.config deleted file mode 100644 index 658b8185c..000000000 --- a/src/System.Net.Http.Formatting.NetCore/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/System.Net.Http.Formatting.NetStandard/System.Net.Http.Formatting.NetStandard.csproj b/src/System.Net.Http.Formatting.NetStandard/System.Net.Http.Formatting.NetStandard.csproj deleted file mode 100644 index 49eb0f3a9..000000000 --- a/src/System.Net.Http.Formatting.NetStandard/System.Net.Http.Formatting.NetStandard.csproj +++ /dev/null @@ -1,258 +0,0 @@ - - - - - {636CA76A-C85C-42E2-B4AA-88046279B3CA} - Library - Properties - System.Net.Http - System.Net.Http.Formatting - $(OutputPath)NetStandard\ - $(OutputPath)$(AssemblyName).xml - $(CodeAnalysis) - ..\Strict.ruleset - /assemblycomparemode:StrongNameIgnoringVersion - false - $(DefineConstants);NETFX_CORE;ASPNETMVC;NOT_CLS_COMPLIANT;NETSTANDARD1_1 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 14.0 - 1591 - v5.0 - - - - Properties\CommonAssemblyInfo.cs - - - Common\Error.cs - - - Common\TaskHelpers.cs - - - Common\TaskHelpersExtensions.cs - - - Common\UriQueryUtility.cs - - - Common\CollectionExtensions.cs - - - Common\ListWrapperCollection.cs - - - FormattingUtilities.cs - - - Formatting\BaseJsonMediaTypeFormatter.cs - - - Formatting\BsonMediaTypeFormatter.cs - - - Formatting\DelegatingEnumerable.cs - - - Formatting\FormDataCollection.cs - - - Formatting\FormUrlEncodedJson.cs - - - Formatting\IFormatterLogger.cs - - - Formatting\JsonMediaTypeFormatter.cs - - - Formatting\MediaTypeConstants.cs - - - Formatting\MediaTypeFormatter.cs - - - Formatting\MediaTypeFormatterCollection.cs - - - Formatting\MediaTypeHeaderValueExtensions.cs - - - Formatting\MediaTypeHeaderValueRange.cs - - - Formatting\ParsedMediaTypeHeaderValue.cs - - - Formatting\Parsers\FormUrlEncodedParser.cs - - - Formatting\Parsers\HttpRequestHeaderParser.cs - - - Formatting\Parsers\HttpRequestLineParser.cs - - - Formatting\Parsers\HttpResponseHeaderParser.cs - - - Formatting\Parsers\HttpStatusLineParser.cs - - - Formatting\Parsers\InternetMessageFormatHeaderParser.cs - - - Formatting\Parsers\MimeMultipartBodyPartParser.cs - - - Formatting\Parsers\MimeMultipartParser.cs - - - Formatting\Parsers\ParserState.cs - - - Formatting\StringComparisonHelper.cs - - - Formatting\XmlMediaTypeFormatter.cs - - - Internal\HttpValueCollection.cs - - - UriExtensions.cs - - - GlobalSuppressions.cs - - - Handlers\HttpProgressEventArgs.cs - - - Handlers\ProgressContent.cs - - - Handlers\ProgressMessageHandler.cs - - - Handlers\ProgressStream.cs - - - HttpClientExtensions.cs - - - HttpClientFactory.cs - - - HttpContentExtensions.cs - - - HttpContentMessageExtensions.cs - - - HttpContentMultipartExtensions.cs - - - HttpHeaderExtensions.cs - - - HttpMessageContent.cs - - - HttpUnsortedHeaders.cs - - - HttpUnsortedRequest.cs - - - HttpUnsortedResponse.cs - - - Internal\AsyncResult.cs - - - Internal\DelegatingStream.cs - - - Internal\ReadOnlyStreamWithEncodingPreamble.cs - - - Internal\TypeExtensions.cs - - - MimeBodyPart.cs - - - MultipartFileData.cs - - - MultipartMemoryStreamProvider.cs - - - MultipartRelatedStreamProvider.cs - - - MultipartStreamProvider.cs - - - ObjectContent.cs - - - ObjectContentOfT.cs - - - PushStreamContent.cs - - - Properties\AssemblyInfo.cs - - - Properties\Resources.Designer.cs - True - True - Resources.resx - - - UnsupportedMediaTypeException.cs - - - Internal\ConcurrentDictionary.cs - - - MediaTypeHeaderValueExtensions.cs - - - - - Properties\CommonWebApiResources.Designer.cs - True - True - CommonWebApiResources.resx - - - - - Properties\CommonWebApiResources.resx - ResXFileCodeGenerator - CommonWebApiResources.Designer.cs - - - - - Properties\Resources.resx - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - - - CodeAnalysisDictionary.xml - - - - - - - - \ No newline at end of file diff --git a/src/System.Net.Http.Formatting.NetStandard/project.json b/src/System.Net.Http.Formatting.NetStandard/project.json deleted file mode 100644 index 0f162d655..000000000 --- a/src/System.Net.Http.Formatting.NetStandard/project.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "supports": {}, - "dependencies": { - "NETStandard.Library": "1.6.0", - "Newtonsoft.Json": "9.0.1", - "System.ComponentModel.EventBasedAsync": "4.0.11", - "System.Diagnostics.Contracts": "4.0.1", - "System.Runtime.Serialization.Xml": "4.1.1", - "System.Xml.XmlSerializer": "4.0.11" - }, - "frameworks": { - "netstandard1.1": {} - } -} \ No newline at end of file diff --git a/src/System.Net.Http.Formatting.ns1_3/ICloneable.cs b/src/System.Net.Http.Formatting.ns1_3/ICloneable.cs new file mode 100644 index 000000000..1fc5b88c5 --- /dev/null +++ b/src/System.Net.Http.Formatting.ns1_3/ICloneable.cs @@ -0,0 +1,9 @@ +// No ICloneable interface in .NET Standard 1.3. + +namespace System +{ + internal interface ICloneable + { + object Clone(); + } +} diff --git a/src/System.Net.Http.Formatting.NetCore/MediaTypeHeaderValueExtensions.cs b/src/System.Net.Http.Formatting.ns1_3/MediaTypeHeaderValueExtensions.cs similarity index 100% rename from src/System.Net.Http.Formatting.NetCore/MediaTypeHeaderValueExtensions.cs rename to src/System.Net.Http.Formatting.ns1_3/MediaTypeHeaderValueExtensions.cs diff --git a/src/System.Net.Http.Formatting.ns1_3/System.Net.Http.Formatting.ns1_3.csproj b/src/System.Net.Http.Formatting.ns1_3/System.Net.Http.Formatting.ns1_3.csproj new file mode 100644 index 000000000..cb723ee1d --- /dev/null +++ b/src/System.Net.Http.Formatting.ns1_3/System.Net.Http.Formatting.ns1_3.csproj @@ -0,0 +1,73 @@ + + + + netstandard1.3 + System.Net.Http + System.Net.Http.Formatting + $(OutputPath)ns1_3\ + $(OutputPath)$(AssemblyName).xml + false + $(DefineConstants);ASPNETHTTPFORMATTING + 1591 + false + $(Configurations);CodeAnalysis + false + + + + + + + + + + + + + + + + + + + + + + + + + %(RecursiveDir)\%(Filename).cs + + + + True + CommonWebApiResources.resx + True + Properties\CommonWebApiResources.Designer.cs + + + ResXFileCodeGenerator + CommonWebApiResources.Designer.cs + Properties\CommonWebApiResources.resx + + + + True + Resources.resx + True + Properties\Resources.Designer.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Properties\Resources.resx + Designer + + + + + diff --git a/src/System.Net.Http.Formatting.ns2_0/System.Net.Http.Formatting.ns2_0.csproj b/src/System.Net.Http.Formatting.ns2_0/System.Net.Http.Formatting.ns2_0.csproj new file mode 100644 index 000000000..b31b98d40 --- /dev/null +++ b/src/System.Net.Http.Formatting.ns2_0/System.Net.Http.Formatting.ns2_0.csproj @@ -0,0 +1,64 @@ + + + + netstandard2.0 + System.Net.Http + System.Net.Http.Formatting + $(OutputPath)ns2_0\ + $(OutputPath)$(AssemblyName).xml + false + $(DefineConstants);ASPNETHTTPFORMATTING + 1591 + false + $(Configurations);CodeAnalysis + false + + + + + + + + + + + + + + + + + + %(RecursiveDir)\%(Filename).cs + + + + True + CommonWebApiResources.resx + True + Properties\CommonWebApiResources.Designer.cs + + + ResXFileCodeGenerator + CommonWebApiResources.Designer.cs + Properties\CommonWebApiResources.resx + + + + True + Resources.resx + True + Properties\Resources.Designer.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Properties\Resources.resx + Designer + + + + + diff --git a/src/System.Net.Http.Formatting/ByteRangeStreamContent.cs b/src/System.Net.Http.Formatting/ByteRangeStreamContent.cs index 587a0fd7f..40edaddb8 100644 --- a/src/System.Net.Http.Formatting/ByteRangeStreamContent.cs +++ b/src/System.Net.Http.Formatting/ByteRangeStreamContent.cs @@ -13,8 +13,8 @@ namespace System.Net.Http { /// /// implementation which provides a byte range view over a stream used to generate HTTP - /// 206 (Partial Content) byte range responses. The supports one or more - /// byte ranges regardless of whether the ranges are consecutive or not. If there is only one range then a + /// 206 (Partial Content) byte range responses. The supports one or more + /// byte ranges regardless of whether the ranges are consecutive or not. If there is only one range then a /// single partial response body containing a Content-Range header is generated. If there are more than one /// ranges then a multipart/byteranges response is generated where each body part contains a range indicated /// by the associated Content-Range header field. @@ -33,9 +33,9 @@ public class ByteRangeStreamContent : HttpContent /// /// implementation which provides a byte range view over a stream used to generate HTTP - /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend - /// of the selected resource represented by the parameter then an - /// is thrown indicating the valid Content-Range of the content. + /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend + /// of the selected resource represented by the parameter then an + /// is thrown indicating the valid Content-Range of the content. /// /// The stream over which to generate a byte range view. /// The range or ranges, typically obtained from the Range HTTP request header field. @@ -47,9 +47,9 @@ public ByteRangeStreamContent(Stream content, RangeHeaderValue range, string med /// /// implementation which provides a byte range view over a stream used to generate HTTP - /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend - /// of the selected resource represented by the parameter then an - /// is thrown indicating the valid Content-Range of the content. + /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend + /// of the selected resource represented by the parameter then an + /// is thrown indicating the valid Content-Range of the content. /// /// The stream over which to generate a byte range view. /// The range or ranges, typically obtained from the Range HTTP request header field. @@ -62,9 +62,9 @@ public ByteRangeStreamContent(Stream content, RangeHeaderValue range, string med /// /// implementation which provides a byte range view over a stream used to generate HTTP - /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend - /// of the selected resource represented by the parameter then an - /// is thrown indicating the valid Content-Range of the content. + /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend + /// of the selected resource represented by the parameter then an + /// is thrown indicating the valid Content-Range of the content. /// /// The stream over which to generate a byte range view. /// The range or ranges, typically obtained from the Range HTTP request header field. @@ -76,9 +76,9 @@ public ByteRangeStreamContent(Stream content, RangeHeaderValue range, MediaTypeH /// /// implementation which provides a byte range view over a stream used to generate HTTP - /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend - /// of the selected resource represented by the parameter then an - /// is thrown indicating the valid Content-Range of the content. + /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend + /// of the selected resource represented by the parameter then an + /// is thrown indicating the valid Content-Range of the content. /// /// The stream over which to generate a byte range view. /// The range or ranges, typically obtained from the Range HTTP request header field. diff --git a/src/System.Net.Http.Formatting/Formatting/BaseJsonMediaTypeFormatter.cs b/src/System.Net.Http.Formatting/Formatting/BaseJsonMediaTypeFormatter.cs index b30a22edf..c25bdba46 100644 --- a/src/System.Net.Http.Formatting/Formatting/BaseJsonMediaTypeFormatter.cs +++ b/src/System.Net.Http.Formatting/Formatting/BaseJsonMediaTypeFormatter.cs @@ -10,9 +10,7 @@ using System.Threading.Tasks; using System.Web.Http; using Newtonsoft.Json; -#if !NETFX_CORE using Newtonsoft.Json.Serialization; -#endif namespace System.Net.Http.Formatting { @@ -21,12 +19,10 @@ namespace System.Net.Http.Formatting /// public abstract class BaseJsonMediaTypeFormatter : MediaTypeFormatter { - // Though MaxDepth is not supported in portable library, we still override JsonReader's MaxDepth + // Though MaxDepth is not supported in netstandard1.3, we still override JsonReader's MaxDepth private int _maxDepth = FormattingUtilities.DefaultMaxDepth; -#if !NETFX_CORE // DataContractResolver is not supported in portable library private readonly IContractResolver _defaultContractResolver; -#endif private JsonSerializerSettings _jsonSerializerSettings; @@ -36,9 +32,7 @@ public abstract class BaseJsonMediaTypeFormatter : MediaTypeFormatter protected BaseJsonMediaTypeFormatter() { // Initialize serializer settings -#if !NETFX_CORE // DataContractResolver is not supported in portable library _defaultContractResolver = new JsonContractResolver(this); -#endif _jsonSerializerSettings = CreateDefaultSerializerSettings(); // Set default supported character encodings @@ -50,19 +44,15 @@ protected BaseJsonMediaTypeFormatter() /// Initializes a new instance of the class. /// /// The instance to copy settings from. -#if !NETFX_CORE [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "MaxDepth is sealed in existing subclasses and its documentation carries warnings.")] -#endif protected BaseJsonMediaTypeFormatter(BaseJsonMediaTypeFormatter formatter) : base(formatter) { Contract.Assert(formatter != null); SerializerSettings = formatter.SerializerSettings; -#if !NETFX_CORE // MaxDepth is not supported in portable library and so _maxDepth never changes there MaxDepth = formatter._maxDepth; -#endif } /// @@ -82,7 +72,6 @@ public JsonSerializerSettings SerializerSettings } } -#if !NETFX_CORE // MaxDepth is not supported in portable library /// /// Gets or sets the maximum depth allowed by this formatter. /// @@ -106,22 +95,15 @@ public virtual int MaxDepth _maxDepth = value; } } -#endif /// /// Creates a instance with the default settings used by the . /// -#if NETFX_CORE - [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This could only be static half the time.")] -#endif public JsonSerializerSettings CreateDefaultSerializerSettings() { return new JsonSerializerSettings() { -#if !NETFX_CORE // DataContractResolver is not supported in portable library ContractResolver = _defaultContractResolver, -#endif - MissingMemberHandling = MissingMemberHandling.Ignore, // Do not change this setting diff --git a/src/System.Net.Http.Formatting/Formatting/BsonMediaTypeFormatter.cs b/src/System.Net.Http.Formatting/Formatting/BsonMediaTypeFormatter.cs index 8b686f0c5..fe6fdef23 100644 --- a/src/System.Net.Http.Formatting/Formatting/BsonMediaTypeFormatter.cs +++ b/src/System.Net.Http.Formatting/Formatting/BsonMediaTypeFormatter.cs @@ -60,7 +60,6 @@ public static MediaTypeHeaderValue DefaultMediaType } } -#if !NETFX_CORE // MaxDepth and DBNull not supported in portable library; no need to override there /// public sealed override int MaxDepth { @@ -101,7 +100,6 @@ public override Task ReadFromStreamAsync(Type type, Stream readStream, H return base.ReadFromStreamAsync(type, readStream, content, formatterLogger); } } -#endif /// public override object ReadFromStream(Type type, Stream readStream, Encoding effectiveEncoding, @@ -195,7 +193,7 @@ public override JsonReader CreateJsonReader(Type type, Stream readStream, Encodi throw Error.ArgumentNull("effectiveEncoding"); } - BsonReader reader = new BsonReader(new BinaryReader(readStream, effectiveEncoding)); + BsonDataReader reader = new BsonDataReader(new BinaryReader(readStream, effectiveEncoding)); try { @@ -234,14 +232,13 @@ public override void WriteToStream(Type type, object value, Stream writeStream, if (value == null) { - // Cannot serialize null at the top level. Json.Net throws Newtonsoft.Json.JsonWriterException : Error - // writing Null value. BSON must start with an Object or Array. Path ''. Fortunately + // Cannot serialize null at the top level. Json.Net throws Newtonsoft.Json.JsonWriterException : Error + // writing Null value. BSON must start with an Object or Array. Path ''. Fortunately // BaseJsonMediaTypeFormatter.ReadFromStream(Type, Stream, HttpContent, IFormatterLogger) treats zero- // length content as null or the default value of a struct. return; } -#if !NETFX_CORE // DBNull not supported in portable library if (value == DBNull.Value) { // ReadFromStreamAsync() override above converts null to DBNull.Value if given Type is DBNull; normally @@ -252,7 +249,6 @@ public override void WriteToStream(Type type, object value, Stream writeStream, // rather than null, and not meet the receiver's expectations. return; } -#endif // See comments in ReadFromStream() above about this special case and the need to include byte[] in it. // Using runtime type here because Json.Net will throw during serialization whenever it cannot handle the @@ -292,7 +288,7 @@ public override JsonWriter CreateJsonWriter(Type type, Stream writeStream, Encod throw Error.ArgumentNull("effectiveEncoding"); } - return new BsonWriter(new BinaryWriter(writeStream, effectiveEncoding)); + return new BsonDataWriter(new BinaryWriter(writeStream, effectiveEncoding)); } // Return true if Json.Net will likely convert value of given type to a Json primitive, not JsonArray nor @@ -302,15 +298,10 @@ private static bool IsSimpleType(Type type) { Contract.Assert(type != null); - bool isSimpleType; -#if NETFX_CORE // TypeDescriptor is not supported in portable library - isSimpleType = type.IsValueType() || type == typeof(string); -#else // CanConvertFrom() check is similar to MVC / Web API ModelMetadata.IsComplexType getters. This is // sufficient for many cases but Json.Net uses JsonConverterAttribute and built-in converters, not type // descriptors. - isSimpleType = TypeDescriptor.GetConverter(type).CanConvertFrom(typeof(string)); -#endif + bool isSimpleType = TypeDescriptor.GetConverter(type).CanConvertFrom(typeof(string)); return isSimpleType; } diff --git a/src/System.Net.Http.Formatting/Formatting/BufferedMediaTypeFormatter.cs b/src/System.Net.Http.Formatting/Formatting/BufferedMediaTypeFormatter.cs index 29554fd07..908ba6221 100644 --- a/src/System.Net.Http.Formatting/Formatting/BufferedMediaTypeFormatter.cs +++ b/src/System.Net.Http.Formatting/Formatting/BufferedMediaTypeFormatter.cs @@ -13,7 +13,7 @@ namespace System.Net.Http.Formatting { /// - /// Base class for writing a synchronous formatter on top of the asynchronous formatter infrastructure. + /// Base class for writing a synchronous formatter on top of the asynchronous formatter infrastructure. /// This does not guarantee non-blocking threads. The only way to guarantee that we don't block a thread on IO is /// to use the asynchronous . /// @@ -219,13 +219,13 @@ private static Stream GetBufferStream(Stream innerStream, int bufferSize) { Contract.Assert(innerStream != null); - // We wrap the inner stream in a non-closing delegating stream so that we allow the user + // We wrap the inner stream in a non-closing delegating stream so that we allow the user // to use the using (...) pattern yet not break the contract of formatters not closing // the inner stream. Stream nonClosingStream = new NonClosingDelegatingStream(innerStream); - // This uses a naive buffering. BufferedStream() will block the thread while it drains the buffer. - // We can explore a smarter implementation that async drains the buffer. + // This uses a naive buffering. BufferedStream() will block the thread while it drains the buffer. + // We can explore a smarter implementation that async drains the buffer. return new BufferedStream(nonClosingStream, bufferSize); } } diff --git a/src/System.Net.Http.Formatting/Formatting/DefaultContentNegotiator.cs b/src/System.Net.Http.Formatting/Formatting/DefaultContentNegotiator.cs index 94b0f9b99..0cf5c36d7 100644 --- a/src/System.Net.Http.Formatting/Formatting/DefaultContentNegotiator.cs +++ b/src/System.Net.Http.Formatting/Formatting/DefaultContentNegotiator.cs @@ -95,7 +95,7 @@ public virtual ContentNegotiationResult Negotiate(Type type, HttpRequestMessage /// /// Determine how well each formatter matches by associating a value - /// with the formatter. Then associate the quality of the match based on q-factors and other parameters. The result of this + /// with the formatter. Then associate the quality of the match based on q-factors and other parameters. The result of this /// method is a collection of the matches found categorized and assigned a quality value. /// /// The type to be serialized. @@ -123,7 +123,7 @@ protected virtual Collection ComputeFormatterMatches(Ty // Go through each formatter to find how well it matches. ListWrapperCollection matches = new ListWrapperCollection(); MediaTypeFormatter[] writingFormatters = GetWritingFormatters(formatters); - for (int i = 0; i < writingFormatters.Length; i++) + for (int i = 0; i < writingFormatters.Length; i++) { MediaTypeFormatter formatter = writingFormatters[i]; MediaTypeFormatterMatch match = null; @@ -161,7 +161,7 @@ protected virtual Collection ComputeFormatterMatches(Ty continue; } - // Check whether we should match on type or stop the matching process. + // Check whether we should match on type or stop the matching process. // The latter is used to generate 406 (Not Acceptable) status codes. bool shouldMatchOnType = ShouldMatchOnType(sortedAcceptValues); @@ -459,7 +459,7 @@ protected virtual MediaTypeFormatterMatch MatchRequestMediaType(HttpRequestMessa /// /// Determine whether to match on type or not. This is used to determine whether to /// generate a 406 response or use the default media type formatter in case there - /// is no match against anything in the request. If ExcludeMatchOnTypeOnly is true + /// is no match against anything in the request. If ExcludeMatchOnTypeOnly is true /// then we don't match on type unless there are no accept headers. /// /// The sorted accept header values to match. @@ -504,7 +504,7 @@ protected virtual MediaTypeFormatterMatch MatchType(Type type, MediaTypeFormatte } /// - /// Sort Accept header values and related header field values with similar syntax rules + /// Sort Accept header values and related header field values with similar syntax rules /// (if more than 1) in descending order based on q-factor. /// /// The header values to sort. @@ -529,7 +529,7 @@ protected virtual IEnumerable SortMediaTypeWith } /// - /// Sort Accept-Charset, Accept-Encoding, Accept-Language and related header field values with similar syntax rules + /// Sort Accept-Charset, Accept-Encoding, Accept-Language and related header field values with similar syntax rules /// (if more than 1) in descending order based on q-factor. /// /// The header values to sort. @@ -554,7 +554,7 @@ protected virtual IEnumerable SortStringWithQualit } /// - /// Evaluates whether a match is better than the current match and if so returns the replacement; otherwise returns the + /// Evaluates whether a match is better than the current match and if so returns the replacement; otherwise returns the /// current match. /// protected virtual MediaTypeFormatterMatch UpdateBestMatch(MediaTypeFormatterMatch current, MediaTypeFormatterMatch potentialReplacement) diff --git a/src/System.Net.Http.Formatting/Formatting/FormDataCollection.cs b/src/System.Net.Http.Formatting/Formatting/FormDataCollection.cs index 21504147b..74a5ea549 100644 --- a/src/System.Net.Http.Formatting/Formatting/FormDataCollection.cs +++ b/src/System.Net.Http.Formatting/Formatting/FormDataCollection.cs @@ -5,40 +5,29 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; -#if !NETFX_CORE using System.Net.Http.Formatting.Internal; -#endif using System.Net.Http.Formatting.Parsers; using System.Text; using System.Threading; using System.Web.Http; -#if NETFX_CORE -using NameValueCollection = System.Net.Http.Formatting.HttpValueCollection; -#endif - namespace System.Net.Http.Formatting { /// /// Represent the form data. - /// - This has 100% fidelity (including ordering, which is important for deserializing ordered array). - /// - using interfaces allows us to optimize the implementation. E.g., we can avoid eagerly string-splitting a 10gb file. - /// - This also provides a convenient place to put extension methods. + /// - This has 100% fidelity (including ordering, which is important for deserializing ordered array). + /// - using interfaces allows us to optimize the implementation. E.g., we can avoid eagerly string-splitting a 10gb file. + /// - This also provides a convenient place to put extension methods. /// -#if NETFX_CORE - internal -#else - public -#endif - class FormDataCollection : IEnumerable> + public class FormDataCollection : IEnumerable> { private readonly IEnumerable> _pairs; private NameValueCollection _nameValueCollection; /// - /// Initialize a form collection around incoming data. - /// The key value enumeration should be immutable. + /// Initialize a form collection around incoming data. + /// The key value enumeration should be immutable. /// /// incoming set of key value pairs. Ordering is preserved. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is the convention for representing FormData")] @@ -52,8 +41,8 @@ public FormDataCollection(IEnumerable> pairs) } /// - /// Initialize a form collection from a query string. - /// Uri and FormURl body have the same schema. + /// Initialize a form collection from a query string. + /// Uri and FormURl body have the same schema. /// public FormDataCollection(Uri uri) { @@ -136,7 +125,7 @@ public NameValueCollection ReadAsNameValueCollection() } /// - /// Get values associated with a given key. If there are multiple values, they're concatenated. + /// Get values associated with a given key. If there are multiple values, they're concatenated. /// public string Get(string key) { @@ -144,7 +133,7 @@ public string Get(string key) } /// - /// Get a value associated with a given key. + /// Get a value associated with a given key. /// public string[] GetValues(string key) { diff --git a/src/System.Net.Http.Formatting/Formatting/FormUrlEncodedJson.cs b/src/System.Net.Http.Formatting/Formatting/FormUrlEncodedJson.cs index 6a295c72c..cb3d53917 100644 --- a/src/System.Net.Http.Formatting/Formatting/FormUrlEncodedJson.cs +++ b/src/System.Net.Http.Formatting/Formatting/FormUrlEncodedJson.cs @@ -13,9 +13,9 @@ namespace System.Net.Http.Formatting { /// - /// This class provides a low-level API for parsing HTML form URL-encoded data, also known as application/x-www-form-urlencoded - /// data. The output of the parser is a instance. - /// This is a low-level API intended for use by other APIs. It has been optimized for performance and + /// This class provides a low-level API for parsing HTML form URL-encoded data, also known as application/x-www-form-urlencoded + /// data. The output of the parser is a instance. + /// This is a low-level API intended for use by other APIs. It has been optimized for performance and /// is not intended to be called directly from user code. /// internal static class FormUrlEncodedJson @@ -31,7 +31,7 @@ internal static class FormUrlEncodedJson /// /// Parses a collection of query string values as a . /// - /// This is a low-level API intended for use by other APIs. It has been optimized for performance and + /// This is a low-level API intended for use by other APIs. It has been optimized for performance and /// is not intended to be called directly from user code. /// The collection of query string name-value pairs parsed in lexical order. Both names /// and values must be un-escaped so that they don't contain any encoding. @@ -44,7 +44,7 @@ public static JObject Parse(IEnumerable> nameValueP /// /// Parses a collection of query string values as a . /// - /// This is a low-level API intended for use by other APIs. It has been optimized for performance and + /// This is a low-level API intended for use by other APIs. It has been optimized for performance and /// is not intended to be called directly from user code. /// The collection of query string name-value pairs parsed in lexical order. Both names /// and values must be un-escaped so that they don't contain any encoding. @@ -58,7 +58,7 @@ public static JObject Parse(IEnumerable> nameValueP /// /// Parses a collection of query string values as a . /// - /// This is a low-level API intended for use by other APIs. It has been optimized for performance and + /// This is a low-level API intended for use by other APIs. It has been optimized for performance and /// is not intended to be called directly from user code. /// The collection of query string name-value pairs parsed in lexical order. Both names /// and values must be un-escaped so that they don't contain any encoding. @@ -72,7 +72,7 @@ public static bool TryParse(IEnumerable> nameValueP /// /// Parses a collection of query string values as a . /// - /// This is a low-level API intended for use by other APIs. It has been optimized for performance and + /// This is a low-level API intended for use by other APIs. It has been optimized for performance and /// is not intended to be called directly from user code. /// The collection of query string name-value pairs parsed in lexical order. Both names /// and values must be un-escaped so that they don't contain any encoding. @@ -87,7 +87,7 @@ public static bool TryParse(IEnumerable> nameValueP /// /// Parses a collection of query string values as a . /// - /// This is a low-level API intended for use by other APIs. It has been optimized for performance and + /// This is a low-level API intended for use by other APIs. It has been optimized for performance and /// is not intended to be called directly from user code. /// The collection of query string name-value pairs parsed in lexical order. Both names /// and values must be un-escaped so that they don't contain any encoding. @@ -112,7 +112,7 @@ private static JObject ParseInternal(IEnumerable> n string key = nameValuePair.Key; string value = nameValuePair.Value; - // value is preserved, even if it's null, "undefined", "null", String.Empty, etc when converting to JToken. + // value is preserved, even if it's null, "undefined", "null", String.Empty, etc when converting to JToken. if (key == null) { diff --git a/src/System.Net.Http.Formatting/Formatting/FormUrlEncodedMediaTypeFormatter.cs b/src/System.Net.Http.Formatting/Formatting/FormUrlEncodedMediaTypeFormatter.cs index 994ab173b..5c8d883af 100644 --- a/src/System.Net.Http.Formatting/Formatting/FormUrlEncodedMediaTypeFormatter.cs +++ b/src/System.Net.Http.Formatting/Formatting/FormUrlEncodedMediaTypeFormatter.cs @@ -13,7 +13,7 @@ namespace System.Net.Http.Formatting { /// - /// class for handling HTML form URL-ended data, also known as application/x-www-form-urlencoded. + /// class for handling HTML form URL-ended data, also known as application/x-www-form-urlencoded. /// public class FormUrlEncodedMediaTypeFormatter : MediaTypeFormatter { @@ -119,7 +119,7 @@ public override bool CanReadType(Type type) throw Error.ArgumentNull("type"); } - // Can't read arbitrary types. + // Can't read arbitrary types. return type == typeof(FormDataCollection) || FormattingUtilities.IsJTokenType(type); } @@ -193,7 +193,7 @@ private object ReadFromStream(Type type, Stream readStream) } /// - /// Reads all name-value pairs encoded as HTML Form URL encoded data and add them to + /// Reads all name-value pairs encoded as HTML Form URL encoded data and add them to /// a collection as UNescaped URI strings. /// /// Stream to read from. diff --git a/src/System.Net.Http.Formatting/Formatting/JsonContractResolver.cs b/src/System.Net.Http.Formatting/Formatting/JsonContractResolver.cs index 95543f96b..2dd063842 100644 --- a/src/System.Net.Http.Formatting/Formatting/JsonContractResolver.cs +++ b/src/System.Net.Http.Formatting/Formatting/JsonContractResolver.cs @@ -29,8 +29,11 @@ public JsonContractResolver(MediaTypeFormatter formatter) } _formatter = formatter; + +#if !NETSTANDARD1_3 // Need this setting to have [Serializable] types serialized correctly IgnoreSerializableAttribute = false; +#endif } // Determines whether a member is required or not and sets the appropriate JsonProperty settings diff --git a/src/System.Net.Http.Formatting/Formatting/JsonMediaTypeFormatter.cs b/src/System.Net.Http.Formatting/Formatting/JsonMediaTypeFormatter.cs index 019c8feb2..a3bb36060 100644 --- a/src/System.Net.Http.Formatting/Formatting/JsonMediaTypeFormatter.cs +++ b/src/System.Net.Http.Formatting/Formatting/JsonMediaTypeFormatter.cs @@ -1,26 +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. -#if !NETFX_CORE using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; -#endif using System.Diagnostics.Contracts; using System.IO; using System.Net.Http.Headers; -#if !NETFX_CORE +#if !NETSTANDARD1_3 // Unnecessary when targeting netstandard1.3. using System.Net.Http.Internal; -using System.Runtime.Serialization.Json; #endif +using System.Runtime.Serialization.Json; using System.Text; using System.Threading; -#if !NETFX_CORE using System.Threading.Tasks; -#endif using System.Web.Http; -#if !NETFX_CORE using System.Xml; -#endif using Newtonsoft.Json; namespace System.Net.Http.Formatting @@ -30,11 +24,9 @@ namespace System.Net.Http.Formatting /// public class JsonMediaTypeFormatter : BaseJsonMediaTypeFormatter { -#if !NETFX_CORE // DataContractJsonSerializer and MediaTypeMappings are not supported in portable library - private ConcurrentDictionary _dataContractSerializerCache = new ConcurrentDictionary(); - private XmlDictionaryReaderQuotas _readerQuotas = FormattingUtilities.CreateDefaultReaderQuotas(); - private RequestHeaderMapping _requestHeaderMapping; -#endif + private readonly ConcurrentDictionary _dataContractSerializerCache = new ConcurrentDictionary(); + private readonly XmlDictionaryReaderQuotas _readerQuotas = FormattingUtilities.CreateDefaultReaderQuotas(); + private readonly RequestHeaderMapping _requestHeaderMapping; /// /// Initializes a new instance of the class. @@ -45,10 +37,8 @@ public JsonMediaTypeFormatter() SupportedMediaTypes.Add(MediaTypeConstants.ApplicationJsonMediaType); SupportedMediaTypes.Add(MediaTypeConstants.TextJsonMediaType); -#if !NETFX_CORE // MediaTypeMappings are not supported in portable library _requestHeaderMapping = new XmlHttpRequestHeaderMapping(); MediaTypeMappings.Add(_requestHeaderMapping); -#endif } /// @@ -60,10 +50,7 @@ protected JsonMediaTypeFormatter(JsonMediaTypeFormatter formatter) { Contract.Assert(formatter != null); -#if !NETFX_CORE // UseDataContractJsonSerializer is not supported in portable library UseDataContractJsonSerializer = formatter.UseDataContractJsonSerializer; -#endif - Indent = formatter.Indent; } @@ -84,7 +71,6 @@ public static MediaTypeHeaderValue DefaultMediaType get { return MediaTypeConstants.ApplicationJsonMediaType; } } -#if !NETFX_CORE // DataContractJsonSerializer is not supported in portable library /// /// Gets or sets a value indicating whether to use by default. /// @@ -92,14 +78,12 @@ public static MediaTypeHeaderValue DefaultMediaType /// true if use by default; otherwise, false. The default is false. /// public bool UseDataContractJsonSerializer { get; set; } -#endif /// - /// Gets or sets a value indicating whether to indent elements when writing data. + /// Gets or sets a value indicating whether to indent elements when writing data. /// public bool Indent { get; set; } -#if !NETFX_CORE // MaxDepth not supported in portable library; no need to override there /// public sealed override int MaxDepth { @@ -113,7 +97,6 @@ public sealed override int MaxDepth _readerQuotas.MaxDepth = value; } } -#endif /// public override JsonReader CreateJsonReader(Type type, Stream readStream, Encoding effectiveEncoding) @@ -163,7 +146,6 @@ public override JsonWriter CreateJsonWriter(Type type, Stream writeStream, Encod return jsonWriter; } -#if !NETFX_CORE // DataContractJsonSerializer not supported in portable library; no need to override there /// public override bool CanReadType(Type type) { @@ -233,10 +215,21 @@ public override object ReadFromStream(Type type, Stream readStream, Encoding eff if (UseDataContractJsonSerializer) { DataContractJsonSerializer dataContractSerializer = GetDataContractSerializer(type); - using (XmlReader reader = JsonReaderWriterFactory.CreateJsonReader(new NonClosingDelegatingStream(readStream), effectiveEncoding, _readerQuotas, null)) - { - return dataContractSerializer.ReadObject(reader); - } + +#if NETSTANDARD1_3 // Unreachable when targeting netstandard1.3. Return just to satisfy the compiler. + return null; +#else + // DCS encodings are limited to UTF8, UTF16BE, and UTF16LE. Convert to UTF8 as we read. + Stream innerStream = + string.Equals(effectiveEncoding.WebName, Utf8Encoding.WebName, StringComparison.OrdinalIgnoreCase) ? + new NonClosingDelegatingStream(readStream) : + new TranscodingStream(readStream, effectiveEncoding, Utf8Encoding, leaveOpen: true); + + // XmlDictionaryReader will always dispose of innerStream when we dispose of the reader. + using XmlDictionaryReader reader = + JsonReaderWriterFactory.CreateJsonReader(innerStream, Utf8Encoding, _readerQuotas, onClose: null); + return dataContractSerializer.ReadObject(reader); +#endif } else { @@ -294,10 +287,18 @@ public override void WriteToStream(Type type, object value, Stream writeStream, } } - DataContractJsonSerializer dataContractSerializer = GetDataContractSerializer(type); - using (XmlWriter writer = JsonReaderWriterFactory.CreateJsonWriter(writeStream, effectiveEncoding, ownsStream: false)) + WritePreamble(writeStream, effectiveEncoding); + if (string.Equals(effectiveEncoding.WebName, Utf8Encoding.WebName, StringComparison.OrdinalIgnoreCase)) { - dataContractSerializer.WriteObject(writer, value); + WriteObject(writeStream, type, value); + } + else + { + // JsonReaderWriterFactory is internal and DataContractJsonSerializer only writes UTF8 for the + // netstandard1.3 project. In addition, DCS encodings are limited to UTF8, UTF16BE, and UTF16LE. + // Convert to UTF8 as we write. + using var innerStream = new TranscodingStream(writeStream, effectiveEncoding, Utf8Encoding, leaveOpen: true); + WriteObject(innerStream, type, value); } } else @@ -306,11 +307,35 @@ public override void WriteToStream(Type type, object value, Stream writeStream, } } + private void WriteObject(Stream stream, Type type, object value) + { + DataContractJsonSerializer dataContractSerializer = GetDataContractSerializer(type); + +#if !NETSTANDARD1_3 // Unreachable when targeting netstandard1.3. + // Do not dispose of the stream. WriteToStream handles that where it's needed. + using XmlWriter writer = JsonReaderWriterFactory.CreateJsonWriter(stream, Utf8Encoding, ownsStream: false); + dataContractSerializer.WriteObject(writer, value); +#endif + } + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Catch all is around an extensibile method")] private DataContractJsonSerializer CreateDataContractSerializer(Type type, bool throwOnError) { Contract.Assert(type != null); +#if NETSTANDARD1_3 // XsdDataContractExporter is not supported in netstandard1.3 + if (throwOnError) + { + throw new PlatformNotSupportedException(Error.Format( + Properties.Resources.JsonMediaTypeFormatter_DCS_NotSupported, + nameof(UseDataContractJsonSerializer))); + } + else + { + return null; + } +#else + DataContractJsonSerializer serializer = null; Exception exception = null; @@ -318,6 +343,7 @@ private DataContractJsonSerializer CreateDataContractSerializer(Type type, bool { // Verify that type is a valid data contract by forcing the serializer to try to create a data contract FormattingUtilities.XsdDataContractExporter.GetRootElementName(type); + serializer = CreateDataContractSerializer(type); } catch (Exception caught) @@ -342,6 +368,7 @@ private DataContractJsonSerializer CreateDataContractSerializer(Type type, bool } return serializer; +#endif } /// @@ -378,6 +405,5 @@ private DataContractJsonSerializer GetDataContractSerializer(Type type) return serializer; } -#endif } } diff --git a/src/System.Net.Http.Formatting/Formatting/MediaTypeFormatter.cs b/src/System.Net.Http.Formatting/Formatting/MediaTypeFormatter.cs index dd7731e1d..20eace069 100644 --- a/src/System.Net.Http.Formatting/Formatting/MediaTypeFormatter.cs +++ b/src/System.Net.Http.Formatting/Formatting/MediaTypeFormatter.cs @@ -1,17 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#if !NETFX_CORE // In portable library we have our own implementation of Concurrent Dictionary which is in the internal namespace using System.Collections.Concurrent; -#endif using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Net.Http.Headers; -#if NETFX_CORE // In portable library we have our own implementation of Concurrent Dictionary which is in the internal namespace -using System.Net.Http.Internal; -#endif using System.Reflection; using System.Text; using System.Threading; @@ -25,6 +20,8 @@ namespace System.Net.Http.Formatting /// public abstract class MediaTypeFormatter { + private protected static readonly Encoding Utf8Encoding = + new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); private const int DefaultMinHttpCollectionKeys = 1; private const int DefaultMaxHttpCollectionKeys = 1000; // same default as ASPNET private const string IWellKnownComparerTypeName = "System.IWellKnownStringEqualityComparer, mscorlib, Version=4.0.0.0, PublicKeyToken=b77a5c561934e089"; @@ -36,10 +33,8 @@ public abstract class MediaTypeFormatter private readonly List _supportedMediaTypes; private readonly List _supportedEncodings; -#if !NETFX_CORE // No MediaTypeMappings in portable library or IRequiredMemberSelector (no model state on client) private readonly List _mediaTypeMappings; private IRequiredMemberSelector _requiredMemberSelector; -#endif /// /// Initializes a new instance of the class. @@ -50,10 +45,8 @@ protected MediaTypeFormatter() SupportedMediaTypes = new MediaTypeHeaderValueCollection(_supportedMediaTypes); _supportedEncodings = new List(); SupportedEncodings = new Collection(_supportedEncodings); -#if !NETFX_CORE // No MediaTypeMappings in portable library _mediaTypeMappings = new List(); MediaTypeMappings = new Collection(_mediaTypeMappings); -#endif } /// @@ -71,15 +64,13 @@ protected MediaTypeFormatter(MediaTypeFormatter formatter) SupportedMediaTypes = formatter.SupportedMediaTypes; _supportedEncodings = formatter._supportedEncodings; SupportedEncodings = formatter.SupportedEncodings; -#if !NETFX_CORE // No MediaTypeMappings in portable library or IRequiredMemberSelector (no model state on client) _mediaTypeMappings = formatter._mediaTypeMappings; MediaTypeMappings = formatter.MediaTypeMappings; _requiredMemberSelector = formatter._requiredMemberSelector; -#endif } /// - /// Gets or sets the maximum number of keys stored in a NameValueCollection. + /// Gets or sets the maximum number of keys stored in a NameValueCollection. /// public static int MaxHttpCollectionKeys { @@ -117,7 +108,7 @@ internal List SupportedMediaTypesInternal /// /// Gets the mutable collection of character encodings supported by /// this instance. The encodings are - /// used when reading or writing data. + /// used when reading or writing data. /// public Collection SupportedEncodings { get; private set; } @@ -126,7 +117,6 @@ internal List SupportedEncodingsInternal get { return _supportedEncodings; } } -#if !NETFX_CORE // No MediaTypeMappings in portable library /// /// Gets the mutable collection of elements used /// by this instance to determine the @@ -138,9 +128,7 @@ internal List MediaTypeMappingsInternal { get { return _mediaTypeMappings; } } -#endif -#if !NETFX_CORE // IRequiredMemberSelector is not in portable libraries because there is no model state on the client. /// /// Gets or sets the used to determine required members. /// @@ -155,7 +143,6 @@ public virtual IRequiredMemberSelector RequiredMemberSelector _requiredMemberSelector = value; } } -#endif internal virtual bool CanWriteAnyTypes { @@ -504,6 +491,15 @@ public static object GetDefaultValueForType(Type type) return null; } + private protected static void WritePreamble(Stream stream, Encoding encoding) + { + byte[] bytes = encoding.GetPreamble(); + if (bytes.Length > 0) + { + stream.Write(bytes, 0, bytes.Length); + } + } + /// /// Collection class that validates it contains only instances /// that are not null and not media ranges. diff --git a/src/System.Net.Http.Formatting/Formatting/MediaTypeFormatterCollection.cs b/src/System.Net.Http.Formatting/Formatting/MediaTypeFormatterCollection.cs index 2a54f050a..864eacded 100644 --- a/src/System.Net.Http.Formatting/Formatting/MediaTypeFormatterCollection.cs +++ b/src/System.Net.Http.Formatting/Formatting/MediaTypeFormatterCollection.cs @@ -59,7 +59,6 @@ public JsonMediaTypeFormatter JsonFormatter get { return Items.OfType().FirstOrDefault(); } } -#if !NETFX_CORE // FormUrlEncodedMediaTypeFormatter is not supported in portable library. /// /// Gets the to use for application/x-www-form-urlencoded data. /// @@ -67,7 +66,6 @@ public FormUrlEncodedMediaTypeFormatter FormUrlEncodedFormatter { get { return Items.OfType().FirstOrDefault(); } } -#endif internal MediaTypeFormatter[] WritingFormatters { @@ -200,10 +198,8 @@ public MediaTypeFormatter FindWriter(Type type, MediaTypeHeaderValue mediaType) public static bool IsTypeExcludedFromValidation(Type type) { return -#if !NETFX_CORE typeof(XmlNode).IsAssignableFrom(type) || typeof(FormDataCollection).IsAssignableFrom(type) || -#endif FormattingUtilities.IsJTokenType(type) || typeof(XObject).IsAssignableFrom(type) || typeof(Type).IsAssignableFrom(type) || @@ -259,10 +255,12 @@ private static IEnumerable CreateDefaultFormatters() return new MediaTypeFormatter[] { new JsonMediaTypeFormatter(), - new XmlMediaTypeFormatter(), -#if !NETFX_CORE - new FormUrlEncodedMediaTypeFormatter() + new XmlMediaTypeFormatter() +#if NETSTANDARD1_3 // XsdDataContractExporter is not supported in netstandard1.3. Cannot use DCS. + { UseXmlSerializer = true } #endif + , + new FormUrlEncodedMediaTypeFormatter() }; } diff --git a/src/System.Net.Http.Formatting/Formatting/MediaTypeHeaderValueExtensions.cs b/src/System.Net.Http.Formatting/Formatting/MediaTypeHeaderValueExtensions.cs index a0cae45d0..7f58a0d18 100644 --- a/src/System.Net.Http.Formatting/Formatting/MediaTypeHeaderValueExtensions.cs +++ b/src/System.Net.Http.Formatting/Formatting/MediaTypeHeaderValueExtensions.cs @@ -17,8 +17,8 @@ internal static class MediaTypeHeaderValueExtensions /// /// Determines whether two instances match. The instance /// is said to match if and only if - /// is a strict subset of the values and parameters of . - /// That is, if the media type and media type parameters of are all present + /// is a strict subset of the values and parameters of . + /// That is, if the media type and media type parameters of are all present /// and match those of then it is a match even though may have additional /// parameters. /// @@ -34,8 +34,8 @@ public static bool IsSubsetOf(this MediaTypeHeaderValue mediaType1, MediaTypeHea /// /// Determines whether two instances match. The instance /// is said to match if and only if - /// is a strict subset of the values and parameters of . - /// That is, if the media type and media type parameters of are all present + /// is a strict subset of the values and parameters of . + /// That is, if the media type and media type parameters of are all present /// and match those of then it is a match even though may have additional /// parameters. /// @@ -75,12 +75,12 @@ public static bool IsSubsetOf(this MediaTypeHeaderValue mediaType1, MediaTypeHea } } - // So far we either have a full match or a subset match. Now check that all of + // So far we either have a full match or a subset match. Now check that all of // mediaType1's parameters are present and equal in mediatype2 // Optimize for the common case where the parameters inherit from Collection and cache the count which is faster for Collection. Collection parameters1 = mediaType1.Parameters.AsCollection(); int parameterCount1 = parameters1.Count; - Collection parameters2 = mediaType2.Parameters.AsCollection(); + Collection parameters2 = mediaType2.Parameters.AsCollection(); int parameterCount2 = parameters2.Count; for (int i = 0; i < parameterCount1; i++) { diff --git a/src/System.Net.Http.Formatting/Formatting/MediaTypeWithQualityHeaderValueComparer.cs b/src/System.Net.Http.Formatting/Formatting/MediaTypeWithQualityHeaderValueComparer.cs index 549d2272f..277759254 100644 --- a/src/System.Net.Http.Formatting/Formatting/MediaTypeWithQualityHeaderValueComparer.cs +++ b/src/System.Net.Http.Formatting/Formatting/MediaTypeWithQualityHeaderValueComparer.cs @@ -8,7 +8,7 @@ namespace System.Net.Http.Formatting { /// Implementation of that can compare accept media type header fields - /// based on their quality values (a.k.a q-values). See + /// based on their quality values (a.k.a q-values). See /// for a comparer for other content negotiation /// header field q-values. internal class MediaTypeWithQualityHeaderValueComparer : IComparer @@ -26,8 +26,8 @@ public static MediaTypeWithQualityHeaderValueComparer QualityComparer /// /// Compares two based on their quality value (a.k.a their "q-value"). - /// Values with identical q-values are considered equal (i.e the result is 0) with the exception that sub-type wild-cards are - /// considered less than specific media types and full wild-cards are considered less than sub-type wild-cards. This allows to + /// Values with identical q-values are considered equal (i.e the result is 0) with the exception that sub-type wild-cards are + /// considered less than specific media types and full wild-cards are considered less than sub-type wild-cards. This allows to /// sort a sequence of following their q-values in the order of specific media types, /// sub-type wildcards, and last any full wild-cards. /// diff --git a/src/System.Net.Http.Formatting/Formatting/ParsedMediaTypeHeaderValue.cs b/src/System.Net.Http.Formatting/Formatting/ParsedMediaTypeHeaderValue.cs index 057730391..fa1e4c259 100644 --- a/src/System.Net.Http.Formatting/Formatting/ParsedMediaTypeHeaderValue.cs +++ b/src/System.Net.Http.Formatting/Formatting/ParsedMediaTypeHeaderValue.cs @@ -40,14 +40,14 @@ public ParsedMediaTypeHeaderValue(MediaTypeHeaderValue mediaTypeHeaderValue) } } - public bool IsAllMediaRange - { - get { return _isAllMediaRange; } + public bool IsAllMediaRange + { + get { return _isAllMediaRange; } } - public bool IsSubtypeMediaRange - { - get { return _isSubtypeMediaRange; } + public bool IsSubtypeMediaRange + { + get { return _isSubtypeMediaRange; } } public bool TypesEqual(ref ParsedMediaTypeHeaderValue other) diff --git a/src/System.Net.Http.Formatting/Formatting/Parsers/FormUrlEncodedParser.cs b/src/System.Net.Http.Formatting/Formatting/Parsers/FormUrlEncodedParser.cs index d7f248d16..90754c123 100644 --- a/src/System.Net.Http.Formatting/Formatting/Parsers/FormUrlEncodedParser.cs +++ b/src/System.Net.Http.Formatting/Formatting/Parsers/FormUrlEncodedParser.cs @@ -11,7 +11,7 @@ namespace System.Net.Http.Formatting.Parsers { /// - /// Buffer-oriented parsing of HTML form URL-ended, also known as application/x-www-form-urlencoded, data. + /// Buffer-oriented parsing of HTML form URL-ended, also known as application/x-www-form-urlencoded, data. /// internal class FormUrlEncodedParser { @@ -54,7 +54,7 @@ private enum NameValueState /// /// Parse a buffer of URL form-encoded name-value pairs and add them to the collection. - /// Bytes are parsed in a consuming manner from the beginning of the buffer meaning that the same bytes can not be + /// Bytes are parsed in a consuming manner from the beginning of the buffer meaning that the same bytes can not be /// present in the buffer. /// /// Buffer from where data is read @@ -243,7 +243,7 @@ private ParserState CopyCurrent(ParserState parseState) } /// - /// Maintains information about the current header field being parsed. + /// Maintains information about the current header field being parsed. /// private class CurrentNameValuePair { @@ -275,9 +275,9 @@ public StringBuilder Value /// The collection to copy into. public void CopyTo(ICollection> nameValuePairs) { - string unescapedName = UriQueryUtility.UrlDecode(_name.ToString()); + string unescapedName = WebUtility.UrlDecode(_name.ToString()); string escapedValue = _value.ToString(); - string value = UriQueryUtility.UrlDecode(escapedValue); + string value = WebUtility.UrlDecode(escapedValue); nameValuePairs.Add(new KeyValuePair(unescapedName, value)); @@ -290,7 +290,7 @@ public void CopyTo(ICollection> nameValuePairs) /// The collection to copy into. public void CopyNameOnlyTo(ICollection> nameValuePairs) { - string unescapedName = UriQueryUtility.UrlDecode(_name.ToString()); + string unescapedName = WebUtility.UrlDecode(_name.ToString()); string value = String.Empty; nameValuePairs.Add(new KeyValuePair(unescapedName, value)); Clear(); diff --git a/src/System.Net.Http.Formatting/Formatting/Parsers/HttpRequestLineParser.cs b/src/System.Net.Http.Formatting/Formatting/Parsers/HttpRequestLineParser.cs index 027270150..b89189f8a 100644 --- a/src/System.Net.Http.Formatting/Formatting/Parsers/HttpRequestLineParser.cs +++ b/src/System.Net.Http.Formatting/Formatting/Parsers/HttpRequestLineParser.cs @@ -56,8 +56,8 @@ private enum HttpRequestLineState } /// - /// Parse an HTTP request line. - /// Bytes are parsed in a consuming manner from the beginning of the request buffer meaning that the same bytes can not be + /// Parse an HTTP request line. + /// Bytes are parsed in a consuming manner from the beginning of the request buffer meaning that the same bytes can not be /// present in the request buffer. /// /// Request buffer from where request is read diff --git a/src/System.Net.Http.Formatting/Formatting/Parsers/HttpStatusLineParser.cs b/src/System.Net.Http.Formatting/Formatting/Parsers/HttpStatusLineParser.cs index e64677e94..86f00f77d 100644 --- a/src/System.Net.Http.Formatting/Formatting/Parsers/HttpStatusLineParser.cs +++ b/src/System.Net.Http.Formatting/Formatting/Parsers/HttpStatusLineParser.cs @@ -58,8 +58,8 @@ private enum HttpStatusLineState } /// - /// Parse an HTTP status line. - /// Bytes are parsed in a consuming manner from the beginning of the response buffer meaning that the same bytes can not be + /// Parse an HTTP status line. + /// Bytes are parsed in a consuming manner from the beginning of the response buffer meaning that the same bytes can not be /// present in the response buffer. /// /// Response buffer from where response is read diff --git a/src/System.Net.Http.Formatting/Formatting/Parsers/InternetMessageFormatHeaderParser.cs b/src/System.Net.Http.Formatting/Formatting/Parsers/InternetMessageFormatHeaderParser.cs index aebfa8c29..ebf22b9ba 100644 --- a/src/System.Net.Http.Formatting/Formatting/Parsers/InternetMessageFormatHeaderParser.cs +++ b/src/System.Net.Http.Formatting/Formatting/Parsers/InternetMessageFormatHeaderParser.cs @@ -10,8 +10,8 @@ namespace System.Net.Http.Formatting.Parsers { /// - /// Buffer-oriented RFC 5322 style Internet Message Format parser which can be used to pass header - /// fields used in HTTP and MIME message entities. + /// Buffer-oriented RFC 5322 style Internet Message Format parser which can be used to pass header + /// fields used in HTTP and MIME message entities. /// internal class InternetMessageFormatHeaderParser { @@ -76,7 +76,7 @@ private enum HeaderFieldState /// /// Parse a buffer of RFC 5322 style header fields and add them to the collection. - /// Bytes are parsed in a consuming manner from the beginning of the buffer meaning that the same bytes can not be + /// Bytes are parsed in a consuming manner from the beginning of the buffer meaning that the same bytes can not be /// present in the buffer. /// /// Request buffer from where request is read @@ -283,7 +283,7 @@ private static ParserState ParseHeaderFields( } /// - /// Maintains information about the current header field being parsed. + /// Maintains information about the current header field being parsed. /// private class CurrentHeaderFieldStore { @@ -320,6 +320,10 @@ public void CopyTo(HttpHeaders headers, bool ignoreHeaderValidation) { var name = _name.ToString(); var value = _value.ToString().Trim(CurrentHeaderFieldStore._linearWhiteSpace); + if (string.Equals("expires", name, StringComparison.OrdinalIgnoreCase)) + { + ignoreHeaderValidation = true; + } if (ignoreHeaderValidation) { diff --git a/src/System.Net.Http.Formatting/Formatting/Parsers/MimeMultipartBodyPartParser.cs b/src/System.Net.Http.Formatting/Formatting/Parsers/MimeMultipartBodyPartParser.cs index 24981c209..4f135c6ed 100644 --- a/src/System.Net.Http.Formatting/Formatting/Parsers/MimeMultipartBodyPartParser.cs +++ b/src/System.Net.Http.Formatting/Formatting/Parsers/MimeMultipartBodyPartParser.cs @@ -11,7 +11,7 @@ namespace System.Net.Http.Formatting.Parsers { /// - /// Complete MIME multipart parser that combines for parsing the MIME message into individual body parts + /// Complete MIME multipart parser that combines for parsing the MIME message into individual body parts /// and for parsing each body part into a MIME header and a MIME body. The caller of the parser is returned /// the resulting MIME bodies which can then be written to some output. /// @@ -104,7 +104,7 @@ public void Dispose() } /// - /// Parses the data provided and generates parsed MIME body part bodies in the form of which are ready to + /// Parses the data provided and generates parsed MIME body part bodies in the form of which are ready to /// write to the output stream. /// /// The data to parse @@ -116,11 +116,11 @@ public IEnumerable ParseBuffer(byte[] data, int bytesRead) bool isFinal = false; // There's a special case here - if we've reached the end of the message and there's no optional - // CRLF, then we're out of bytes to read, but we have finished the message. + // CRLF, then we're out of bytes to read, but we have finished the message. // - // If IsWaitingForEndOfMessage is true and we're at the end of the stream, then we're going to - // call into the parser again with an empty array as the buffer to signal the end of the parse. - // Then the final boundary segment will be marked as complete. + // If IsWaitingForEndOfMessage is true and we're at the end of the stream, then we're going to + // call into the parser again with an empty array as the buffer to signal the end of the parse. + // Then the final boundary segment will be marked as complete. if (bytesRead == 0 && !_mimeParser.IsWaitingForEndOfMessage) { CleanupCurrentBodyPart(); @@ -195,7 +195,7 @@ public IEnumerable ParseBuffer(byte[] data, int bytesRead) } else { - // Otherwise return what we have + // Otherwise return what we have yield return _currentBodyPart; } } diff --git a/src/System.Net.Http.Formatting/Formatting/Parsers/MimeMultipartParser.cs b/src/System.Net.Http.Formatting/Formatting/Parsers/MimeMultipartParser.cs index 734124566..40b83e617 100644 --- a/src/System.Net.Http.Formatting/Formatting/Parsers/MimeMultipartParser.cs +++ b/src/System.Net.Http.Formatting/Formatting/Parsers/MimeMultipartParser.cs @@ -122,7 +122,7 @@ public enum State /// DataTooBig, } - + public bool CanParseMore(int bytesRead, int bytesConsumed) { if (bytesConsumed < bytesRead) @@ -147,7 +147,7 @@ public bool CanParseMore(int bytesRead, int bytesConsumed) /// /// Parse a MIME multipart message. Bytes are parsed in a consuming - /// manner from the beginning of the request buffer meaning that the same bytes can not be + /// manner from the beginning of the request buffer meaning that the same bytes can not be /// present in the request buffer. /// /// Request buffer from where request is read @@ -156,7 +156,7 @@ public bool CanParseMore(int bytesRead, int bytesConsumed) /// Any body part that was considered as a potential MIME multipart boundary but which was in fact part of the body. /// The bulk of the body part. /// Indicates whether the final body part has been found. - /// In order to get the complete body part, the caller is responsible for concatenating the contents of the + /// In order to get the complete body part, the caller is responsible for concatenating the contents of the /// and out parameters. /// State of the parser. [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exception is translated to parse state.")] @@ -375,7 +375,7 @@ private static State ParseBodyPart( goto quit; } } - + if (bytesConsumed > segmentStart) { if (!currentBodyPart.AppendBoundary(buffer, segmentStart, bytesConsumed - segmentStart)) @@ -391,7 +391,7 @@ private static State ParseBodyPart( case BodyPartState.AfterBoundary: // This state means that we just saw the end of a boundary. It might by a 'normal' boundary, in which - // case it's followed by optional whitespace and a CRLF. Or it might be the 'final' boundary and will + // case it's followed by optional whitespace and a CRLF. Or it might be the 'final' boundary and will // be followed by '--', optional whitespace and an optional CRLF. if (buffer[bytesConsumed] == MimeMultipartParser.Dash && !currentBodyPart.IsFinal) { @@ -456,13 +456,13 @@ private static State ParseBodyPart( { currentBodyPart.AppendBoundary(MimeMultipartParser.Dash); bytesConsumed++; - + if (currentBodyPart.IsBoundaryComplete()) { Debug.Assert(currentBodyPart.IsFinal); - // If we get in here, it means we've see the trailing '--' of the last boundary - in order to consume all of the - // remaining bytes, we don't mark the parse as complete again - wait until this method is called again with the + // If we get in here, it means we've see the trailing '--' of the last boundary - in order to consume all of the + // remaining bytes, we don't mark the parse as complete again - wait until this method is called again with the // empty buffer to do that. bodyPartState = BodyPartState.AfterBoundary; parseStatus = State.NeedMoreData; @@ -658,9 +658,9 @@ public void AppendBoundary(byte data) /// The number of bytes to append. public bool AppendBoundary(byte[] data, int offset, int count) { - // Check that potential boundary is not bigger than our reference boundary. - // Allow for 2 extra characters to include the final boundary which ends with - // an additional "--" sequence + plus up to 4 LWS characters (which are allowed). + // Check that potential boundary is not bigger than our reference boundary. + // Allow for 2 extra characters to include the final boundary which ends with + // an additional "--" sequence + plus up to 4 LWS characters (which are allowed). if (_boundaryLength + count > _referenceBoundaryLength + 6) { return false; @@ -753,7 +753,7 @@ public bool IsBoundaryComplete() { return false; } - + if (_boundaryLength < _referenceBoundaryLength) { return false; @@ -797,9 +797,9 @@ private string DebuggerToString() var boundary = Encoding.UTF8.GetString(_boundary, 0, _boundaryLength); return String.Format( - CultureInfo.InvariantCulture, - "Expected: {0} *** Current: {1}", - referenceBoundary, + CultureInfo.InvariantCulture, + "Expected: {0} *** Current: {1}", + referenceBoundary, boundary); } } diff --git a/src/System.Net.Http.Formatting/Formatting/RequestHeaderMapping.cs b/src/System.Net.Http.Formatting/Formatting/RequestHeaderMapping.cs index 3deee8ca3..845d8903d 100644 --- a/src/System.Net.Http.Formatting/Formatting/RequestHeaderMapping.cs +++ b/src/System.Net.Http.Formatting/Formatting/RequestHeaderMapping.cs @@ -23,9 +23,9 @@ public class RequestHeaderMapping : MediaTypeMapping /// Name of the header to match. /// The header value to match. /// The value comparison to use when matching . - /// if set to true then is + /// if set to true then is /// considered a match if it matches a substring of the actual header value. - /// The media type to use if and + /// The media type to use if and /// is considered a match. public RequestHeaderMapping(string headerName, string headerValue, StringComparison valueComparison, bool isValueSubstring, string mediaType) : base(mediaType) @@ -39,9 +39,9 @@ public RequestHeaderMapping(string headerName, string headerValue, StringCompari /// Name of the header to match. /// The header value to match. /// The to use when matching . - /// if set to true then is + /// if set to true then is /// considered a match if it matches a substring of the actual header value. - /// The to use if and + /// The to use if and /// is considered a match. public RequestHeaderMapping(string headerName, string headerValue, StringComparison valueComparison, bool isValueSubstring, MediaTypeHeaderValue mediaType) : base(mediaType) @@ -65,7 +65,7 @@ public RequestHeaderMapping(string headerName, string headerValue, StringCompari public StringComparison HeaderValueComparison { get; private set; } /// - /// Gets a value indicating whether is + /// Gets a value indicating whether is /// a matched as a substring of the actual header value. /// this instance is value substring. /// diff --git a/src/System.Net.Http.Formatting/Formatting/StringComparisonHelper.cs b/src/System.Net.Http.Formatting/Formatting/StringComparisonHelper.cs index 8dade6d2d..8f45ee70c 100644 --- a/src/System.Net.Http.Formatting/Formatting/StringComparisonHelper.cs +++ b/src/System.Net.Http.Formatting/Formatting/StringComparisonHelper.cs @@ -23,7 +23,7 @@ public static bool IsDefined(StringComparison value) { return value == StringComparison.CurrentCulture || value == StringComparison.CurrentCultureIgnoreCase || -#if !NETFX_CORE +#if !NETSTANDARD1_3 value == StringComparison.InvariantCulture || value == StringComparison.InvariantCultureIgnoreCase || #endif diff --git a/src/System.Net.Http.Formatting/Formatting/StringWithQualityHeaderValueComparer.cs b/src/System.Net.Http.Formatting/Formatting/StringWithQualityHeaderValueComparer.cs index c10caf277..6ded7c717 100644 --- a/src/System.Net.Http.Formatting/Formatting/StringWithQualityHeaderValueComparer.cs +++ b/src/System.Net.Http.Formatting/Formatting/StringWithQualityHeaderValueComparer.cs @@ -9,9 +9,9 @@ namespace System.Net.Http.Formatting { /// /// Implementation of that can compare content negotiation header fields - /// based on their quality values (a.k.a q-values). This applies to values used in accept-charset, - /// accept-encoding, accept-language and related header fields with similar syntax rules. See - /// for a comparer for media type + /// based on their quality values (a.k.a q-values). This applies to values used in accept-charset, + /// accept-encoding, accept-language and related header fields with similar syntax rules. See + /// for a comparer for media type /// q-values. /// internal class StringWithQualityHeaderValueComparer : IComparer diff --git a/src/System.Net.Http.Formatting/Formatting/XmlMediaTypeFormatter.cs b/src/System.Net.Http.Formatting/Formatting/XmlMediaTypeFormatter.cs index bec831de8..76ee18f3d 100644 --- a/src/System.Net.Http.Formatting/Formatting/XmlMediaTypeFormatter.cs +++ b/src/System.Net.Http.Formatting/Formatting/XmlMediaTypeFormatter.cs @@ -1,9 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#if !NETFX_CORE // In portable library we have our own implementation of Concurrent Dictionary which is in the internal namespace using System.Collections.Concurrent; -#endif using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; @@ -57,9 +55,7 @@ protected XmlMediaTypeFormatter(XmlMediaTypeFormatter formatter) { UseXmlSerializer = formatter.UseXmlSerializer; WriterSettings = formatter.WriterSettings; -#if !NETFX_CORE // MaxDepth is not supported in portable libraries MaxDepth = formatter.MaxDepth; -#endif } /// @@ -67,8 +63,8 @@ protected XmlMediaTypeFormatter(XmlMediaTypeFormatter formatter) /// /// /// - /// The default media type does not have any charset parameter as - /// the can be configured on a per + /// The default media type does not have any charset parameter as + /// the can be configured on a per /// instance basis. /// /// Because is mutable, the value @@ -89,7 +85,7 @@ public static MediaTypeHeaderValue DefaultMediaType public bool UseXmlSerializer { get; set; } /// - /// Gets or sets a value indicating whether to indent elements when writing data. + /// Gets or sets a value indicating whether to indent elements when writing data. /// public bool Indent { @@ -108,7 +104,6 @@ public bool Indent /// public XmlWriterSettings WriterSettings { get; private set; } -#if !NETFX_CORE // MaxDepth is not supported in portable libraries /// /// Gets or sets the maximum depth allowed by this formatter. /// @@ -128,7 +123,6 @@ public int MaxDepth _readerQuotas.MaxDepth = value; } } -#endif /// /// Registers the to use to read or write @@ -343,12 +337,14 @@ protected internal virtual XmlReader CreateXmlReader(Stream readStream, HttpCont { // Get the character encoding for the content Encoding effectiveEncoding = SelectCharacterEncoding(content == null ? null : content.Headers); -#if NETFX_CORE - // Force a preamble into the stream, since CreateTextReader in WinRT only supports auto-detecting encoding. - return XmlDictionaryReader.CreateTextReader(new ReadOnlyStreamWithEncodingPreamble(readStream, effectiveEncoding), _readerQuotas); -#else - return XmlDictionaryReader.CreateTextReader(new NonClosingDelegatingStream(readStream), effectiveEncoding, _readerQuotas, null); -#endif + + // DCS encodings are limited to UTF8, UTF16BE, and UTF16LE. Convert to UTF8 as we read. + Stream innerStream = string.Equals(effectiveEncoding.WebName, Utf8Encoding.WebName, StringComparison.OrdinalIgnoreCase) ? + new NonClosingDelegatingStream(readStream) : + new TranscodingStream(readStream, effectiveEncoding, Utf8Encoding, leaveOpen: true); + + // XmlDictionaryReader will always dispose of innerStream when caller disposes of the reader. + return XmlDictionaryReader.CreateTextReader(innerStream, Utf8Encoding, _readerQuotas, onClose: null); } /// @@ -439,9 +435,20 @@ protected internal virtual object GetSerializer(Type type, object value, HttpCon protected internal virtual XmlWriter CreateXmlWriter(Stream writeStream, HttpContent content) { Encoding effectiveEncoding = SelectCharacterEncoding(content != null ? content.Headers : null); + WritePreamble(writeStream, effectiveEncoding); + + // DCS encodings are limited to UTF8, UTF16BE, and UTF16LE. Convert to UTF8 as we read. + Stream innerStream = string.Equals(effectiveEncoding.WebName, Utf8Encoding.WebName, StringComparison.OrdinalIgnoreCase) ? + writeStream : + new TranscodingStream(writeStream, effectiveEncoding, Utf8Encoding, leaveOpen: true); + XmlWriterSettings writerSettings = WriterSettings.Clone(); - writerSettings.Encoding = effectiveEncoding; - return XmlWriter.Create(writeStream, writerSettings); + writerSettings.Encoding = Utf8Encoding; + + // Have XmlWriter dispose of innerStream when caller disposes of the writer if using a TranscodingStream. + writerSettings.CloseOutput = writeStream != innerStream; + + return XmlWriter.Create(innerStream, writerSettings); } /// @@ -504,6 +511,23 @@ public object InvokeGetSerializer(Type type, object value, HttpContent content) private object CreateDefaultSerializer(Type type, bool throwOnError) { Contract.Assert(type != null, "type cannot be null."); + +#if NETSTANDARD1_3 // XsdDataContractExporter is not supported in netstandard1.3 + if (!UseXmlSerializer) + { + if (throwOnError) + { + throw new PlatformNotSupportedException(Error.Format( + Properties.Resources.XmlMediaTypeFormatter_DCS_NotSupported, + nameof(UseXmlSerializer))); + } + else + { + return null; + } + } +#endif + Exception exception = null; object serializer = null; @@ -515,12 +539,12 @@ private object CreateDefaultSerializer(Type type, bool throwOnError) } else { -#if !NETFX_CORE - // REVIEW: Is there something comparable in WinRT? +#if !NETSTANDARD1_3 // Unreachable when targeting netstandard1.3. // Verify that type is a valid data contract by forcing the serializer to try to create a data contract FormattingUtilities.XsdDataContractExporter.GetRootElementName(type); -#endif + serializer = CreateDataContractSerializer(type); +#endif } } catch (Exception caught) diff --git a/src/System.Net.Http.Formatting/FormattingUtilities.cs b/src/System.Net.Http.Formatting/FormattingUtilities.cs index dd61bcf39..2d296a18c 100644 --- a/src/System.Net.Http.Formatting/FormattingUtilities.cs +++ b/src/System.Net.Http.Formatting/FormattingUtilities.cs @@ -18,7 +18,7 @@ namespace System.Net.Http internal static class FormattingUtilities { // Supported date formats for input. - private static readonly string[] dateFormats = new string[] + private static readonly string[] dateFormats = new string[] { // "r", // RFC 1123, required output format but too strict for input "ddd, d MMM yyyy H:m:s 'GMT'", // RFC 1123 (r, except it allows both 1 and 01 for date and time) @@ -30,8 +30,9 @@ internal static class FormattingUtilities "d MMM yy H:m:s 'GMT'", // RFC 1123, no day-of-week, short year "d MMM yy H:m:s", // RFC 1123, no day-of-week, short year, no zone - "dddd, d'-'MMM'-'yy H:m:s 'GMT'", // RFC 850 + "dddd, d'-'MMM'-'yy H:m:s 'GMT'", // RFC 850, short year "dddd, d'-'MMM'-'yy H:m:s", // RFC 850 no zone + "ddd, d'-'MMM'-'yyyy H:m:s 'GMT'", // RFC 850, long year "ddd MMM d H:m:s yyyy", // ANSI C's asctime() format "ddd, d MMM yyyy H:m:s zzz", // RFC 5322 @@ -113,7 +114,7 @@ internal static class FormattingUtilities /// public static readonly Type QueryableInterfaceGenericType = typeof(IQueryable<>); -#if !NETFX_CORE // XsdDataContractExporter is not supported in portable libraries +#if !NETSTANDARD1_3 // XsdDataContractExporter is not supported in netstandard1.3 /// /// An instance of . /// @@ -133,7 +134,7 @@ public static bool IsJTokenType(Type type) } /// - /// Creates an empty instance. The only way is to get it from a dummy + /// Creates an empty instance. The only way is to get it from a dummy /// instance. /// /// The created instance. @@ -165,9 +166,6 @@ public static HttpContentHeaders CreateEmptyContentHeaders() /// public static XmlDictionaryReaderQuotas CreateDefaultReaderQuotas() { -#if NETFX_CORE // MaxDepth is a DOS mitigation. We don't support MaxDepth in portable libraries because it is strictly client side. - return XmlDictionaryReaderQuotas.Max; -#else return new XmlDictionaryReaderQuotas() { MaxArrayLength = Int32.MaxValue, @@ -176,7 +174,6 @@ public static XmlDictionaryReaderQuotas CreateDefaultReaderQuotas() MaxNameTableCharCount = Int32.MaxValue, MaxStringContentLength = Int32.MaxValue }; -#endif } /// diff --git a/src/System.Net.Http.Formatting/GlobalSuppressions.cs b/src/System.Net.Http.Formatting/GlobalSuppressions.cs index deefc5652..d815e56e6 100644 --- a/src/System.Net.Http.Formatting/GlobalSuppressions.cs +++ b/src/System.Net.Http.Formatting/GlobalSuppressions.cs @@ -6,3 +6,5 @@ [assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")] [assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "System.Net.Http.Headers", Justification = "We follow the layout of System.Net.Http.")] [assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "System.Net.Http.Handlers", Justification = "Handlers provide an extensibility hook which we want to keep in a separate namespace.")] +// Some resources are specific to the netstandard1.3 assembly +[assembly: SuppressMessage("Microsoft.Web.FxCop", "MW1000:UnusedResourceUsageRule", Justification = "There are a few unused resources due to missing netstandard1.3 features.")] diff --git a/src/System.Net.Http.Formatting/Handlers/ProgressStream.cs b/src/System.Net.Http.Formatting/Handlers/ProgressStream.cs index fe545f9a2..eff766608 100644 --- a/src/System.Net.Http.Formatting/Handlers/ProgressStream.cs +++ b/src/System.Net.Http.Formatting/Handlers/ProgressStream.cs @@ -10,7 +10,7 @@ namespace System.Net.Http.Handlers { /// - /// This implementation of registers how much data has been + /// This implementation of registers how much data has been /// read (received) versus written (sent) for a particular HTTP operation. The implementation /// is client side in that the total bytes to send is taken from the request and the total /// bytes to read is taken from the response. In a server side scenario, it would be the @@ -67,7 +67,8 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, ReportBytesReceived(readCount, userState: null); return readCount; } -#if !NETFX_CORE // BeginX and EndX are not supported on streams in portable libraries + +#if !NETSTANDARD1_3 // BeginX and EndX are not supported on Streams in netstandard1.3 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return InnerStream.BeginRead(buffer, offset, count, callback, state); @@ -99,7 +100,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc ReportBytesSent(count, userState: null); } -#if !NETFX_CORE // BeginX and EndX are not supported on streams in portable libraries +#if !NETSTANDARD1_3 // BeginX and EndX are not supported on Streams in netstandard1.3 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return new ProgressWriteAsyncResult(InnerStream, this, buffer, offset, count, callback, state); diff --git a/src/System.Net.Http.Formatting/HttpContentFormDataExtensions.cs b/src/System.Net.Http.Formatting/HttpContentFormDataExtensions.cs index 3ef7afc6a..72ebb40c7 100644 --- a/src/System.Net.Http.Formatting/HttpContentFormDataExtensions.cs +++ b/src/System.Net.Http.Formatting/HttpContentFormDataExtensions.cs @@ -12,7 +12,7 @@ namespace System.Net.Http { /// - /// Extension methods to allow HTML form URL-encoded data, also known as application/x-www-form-urlencoded, + /// Extension methods to allow HTML form URL-encoded data, also known as application/x-www-form-urlencoded, /// to be read from instances. /// [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/System.Net.Http.Formatting/HttpContentMessageExtensions.cs b/src/System.Net.Http.Formatting/HttpContentMessageExtensions.cs index dd801b604..fdc518c54 100644 --- a/src/System.Net.Http.Formatting/HttpContentMessageExtensions.cs +++ b/src/System.Net.Http.Formatting/HttpContentMessageExtensions.cs @@ -126,7 +126,7 @@ public static Task ReadAsHttpRequestMessageAsync(this HttpCo /// Read the as an . /// /// The content to read. - /// The URI scheme to use for the request URI (the + /// The URI scheme to use for the request URI (the /// URI scheme is not actually part of the HTTP Request URI and so must be provided externally). /// Size of the buffer. /// A task object representing reading the content as an . @@ -140,7 +140,7 @@ public static Task ReadAsHttpRequestMessageAsync(this HttpCo /// Read the as an . /// /// The content to read. - /// The URI scheme to use for the request URI (the + /// The URI scheme to use for the request URI (the /// URI scheme is not actually part of the HTTP Request URI and so must be provided externally). /// Size of the buffer. /// The token to monitor for cancellation requests. @@ -157,7 +157,7 @@ public static Task ReadAsHttpRequestMessageAsync(this HttpCo /// Read the as an . /// /// The content to read. - /// The URI scheme to use for the request URI (the + /// The URI scheme to use for the request URI (the /// URI scheme is not actually part of the HTTP Request URI and so must be provided externally). /// Size of the buffer. /// The max length of the HTTP header. @@ -174,7 +174,7 @@ public static Task ReadAsHttpRequestMessageAsync(this HttpCo /// Read the as an . /// /// The content to read. - /// The URI scheme to use for the request URI (the + /// The URI scheme to use for the request URI (the /// URI scheme is not actually part of the HTTP Request URI and so must be provided externally). /// Size of the buffer. /// The max length of the HTTP header. @@ -223,7 +223,7 @@ private static async Task ReadAsHttpRequestMessageAsyncCore( HttpUnsortedRequest httpRequest = new HttpUnsortedRequest(); HttpRequestHeaderParser parser = new HttpRequestHeaderParser(httpRequest, - HttpRequestHeaderParser.DefaultMaxRequestLineSize, maxHeaderSize); + Math.Max(HttpRequestHeaderParser.DefaultMaxRequestLineSize, maxHeaderSize), maxHeaderSize); ParserState parseStatus; byte[] buffer = new byte[bufferSize]; @@ -451,7 +451,7 @@ private static HttpContent CreateHeaderFields(HttpHeaders source, HttpHeaders de Contract.Assert(destination != null, "destination headers cannot be null"); Contract.Assert(contentStream != null, "contentStream must be non null"); HttpContentHeaders contentHeaders = null; - HttpContent content = null; + HttpContent content; // Set the header fields foreach (KeyValuePair> header in source) @@ -467,7 +467,8 @@ private static HttpContent CreateHeaderFields(HttpHeaders source, HttpHeaders de } } - // If we have content headers then create an HttpContent for this Response + // If we have content headers then create an HttpContent for this request or response. Otherwise, + // provide a HttpContent instance to overwrite the null or EmptyContent value. if (contentHeaders != null) { // Need to rewind the input stream to be at the position right after the HTTP header @@ -481,6 +482,10 @@ private static HttpContent CreateHeaderFields(HttpHeaders source, HttpHeaders de content = new StreamContent(contentStream); contentHeaders.CopyTo(content.Headers); } + else + { + content = new StreamContent(Stream.Null); + } return content; } diff --git a/src/System.Net.Http.Formatting/HttpContentMultipartExtensions.cs b/src/System.Net.Http.Formatting/HttpContentMultipartExtensions.cs index dce8ce8fa..e9671d5b2 100644 --- a/src/System.Net.Http.Formatting/HttpContentMultipartExtensions.cs +++ b/src/System.Net.Http.Formatting/HttpContentMultipartExtensions.cs @@ -41,9 +41,9 @@ public static bool IsMimeMultipartContent(this HttpContent content) } /// - /// Determines whether the specified content is MIME multipart content with the + /// Determines whether the specified content is MIME multipart content with the /// specified subtype. For example, the subtype mixed would match content - /// with a content type of multipart/mixed. + /// with a content type of multipart/mixed. /// /// The content. /// The MIME multipart subtype to match. @@ -91,7 +91,7 @@ public static Task ReadAsMultipartAsync(this Http /// /// Reads all body parts within a MIME multipart message using the provided instance - /// to determine where the contents of each body part is written. + /// to determine where the contents of each body part is written. /// /// The with which to process the data. /// An existing instance to use for the object's content. @@ -104,7 +104,7 @@ public static Task ReadAsMultipartAsync(this HttpContent content, T stream /// /// Reads all body parts within a MIME multipart message using the provided instance - /// to determine where the contents of each body part is written. + /// to determine where the contents of each body part is written. /// /// The with which to process the data. /// An existing instance to use for the object's content. diff --git a/src/System.Net.Http.Formatting/HttpMessageContent.cs b/src/System.Net.Http.Formatting/HttpMessageContent.cs index 1d90b16d8..c182d40c8 100644 --- a/src/System.Net.Http.Formatting/HttpMessageContent.cs +++ b/src/System.Net.Http.Formatting/HttpMessageContent.cs @@ -205,6 +205,7 @@ protected override async Task SerializeToStreamAsync(Stream stream, TransportCon protected override bool TryComputeLength(out long length) { // We have four states we could be in: + // 0. We have content and it knows its ContentLength. // 1. We have content, but the task is still running or finished without success // 2. We have content, the task has finished successfully, and the stream came back as a null or non-seekable // 3. We have content, the task has finished successfully, and the stream is seekable, so we know its length @@ -214,11 +215,13 @@ protected override bool TryComputeLength(out long length) // For #3, we return true & the size of our headers + the content length // For #4, we return true & the size of our headers - bool hasContent = _streamTask.Value != null; length = 0; - // Cases #1, #2, #3 - if (hasContent) + if (Content?.Headers.ContentLength is not null) + { + length = (long)Content.Headers.ContentLength; // Case #0 + } + else if (_streamTask.Value is not null) { Stream readStream; if (!_streamTask.Value.TryGetResult(out readStream) // Case #1 @@ -356,12 +359,21 @@ private byte[] SerializeHeader() private void ValidateStreamForReading(Stream stream) { + // Stream is null case should be an extreme, incredibly unlikely corner case. Every HttpContent from + // the framework (see dotnet/runtime or .NET Framework reference source) provides a non-null Stream + // in the ReadAsStreamAsync task's return value. Likely need a poorly-designed derived HttpContent + // to hit this. Mostly ignoring the fact this message doesn't make much sense for the case. + if (stream is null || !stream.CanRead) + { + throw Error.NotSupported(Properties.Resources.NotSupported_UnreadableStream); + } + // If the content needs to be written to a target stream a 2nd time, then the stream must support - // seeking (e.g. a FileStream), otherwise the stream can't be copied a second time to a target + // seeking (e.g. a FileStream), otherwise the stream can't be copied a second time to a target // stream (e.g. a NetworkStream). if (_contentConsumed) { - if (stream != null && stream.CanRead) + if (stream.CanSeek) { stream.Position = 0; } diff --git a/src/System.Net.Http.Formatting/HttpRequestMessageExtensions.cs b/src/System.Net.Http.Formatting/HttpRequestMessageExtensions.cs index a503f148b..b2e568eaa 100644 --- a/src/System.Net.Http.Formatting/HttpRequestMessageExtensions.cs +++ b/src/System.Net.Http.Formatting/HttpRequestMessageExtensions.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Web.Http; namespace System.Net.Http @@ -29,6 +30,7 @@ public static HttpResponseMessage CreateResponse(this HttpRequestMessage request return new HttpResponseMessage { + Content = new StreamContent(Stream.Null), StatusCode = statusCode, RequestMessage = request }; @@ -49,6 +51,7 @@ public static HttpResponseMessage CreateResponse(this HttpRequestMessage request return new HttpResponseMessage { + Content = new StreamContent(Stream.Null), RequestMessage = request }; } diff --git a/src/System.Net.Http.Formatting/Internal/ByteRangeStream.cs b/src/System.Net.Http.Formatting/Internal/ByteRangeStream.cs index b519144bc..a4fce9a3f 100644 --- a/src/System.Net.Http.Formatting/Internal/ByteRangeStream.cs +++ b/src/System.Net.Http.Formatting/Internal/ByteRangeStream.cs @@ -3,12 +3,14 @@ using System.IO; using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; using System.Web.Http; namespace System.Net.Http.Internal { /// - /// Stream which only exposes a read-only only range view of an + /// Stream which only exposes a read-only only range view of an /// inner stream. /// internal class ByteRangeStream : DelegatingStream @@ -16,7 +18,7 @@ internal class ByteRangeStream : DelegatingStream // The offset stream position at which the range starts. private readonly long _lowerbounds; - // The total number of bytes within the range. + // The total number of bytes within the range. private readonly long _totalCount; // The current number of bytes read into the range @@ -92,16 +94,40 @@ public override bool CanWrite get { return false; } } + public override long Position + { + get + { + return _currentCount; + } + set + { + if (value < 0) + { + throw Error.ArgumentMustBeGreaterThanOrEqualTo("value", value, 0L); + } + + _currentCount = value; + } + } + +#if !NETSTANDARD1_3 // BeginX and EndX are not supported on Streams in netstandard1.3 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return base.BeginRead(buffer, offset, PrepareStreamForRangeRead(count), callback, state); } +#endif public override int Read(byte[] buffer, int offset, int count) { return base.Read(buffer, offset, PrepareStreamForRangeRead(count)); } + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + return base.ReadAsync(buffer, offset, PrepareStreamForRangeRead(count), cancellationToken); + } + public override int ReadByte() { int effectiveCount = PrepareStreamForRangeRead(1); @@ -109,9 +135,35 @@ public override int ReadByte() { return -1; } + return base.ReadByte(); } + public override long Seek(long offset, SeekOrigin origin) + { + switch (origin) + { + case SeekOrigin.Begin: + _currentCount = offset; + break; + case SeekOrigin.Current: + _currentCount = _currentCount + offset; + break; + case SeekOrigin.End: + _currentCount = _totalCount + offset; + break; + default: + throw Error.InvalidEnumArgument("origin", (int)origin, typeof(SeekOrigin)); + } + + if (_currentCount < 0L) + { + throw new IOException(Properties.Resources.ByteRangeStreamInvalidOffset); + } + + return _currentCount; + } + public override void SetLength(long value) { throw Error.NotSupported(Properties.Resources.ByteRangeStreamReadOnly); @@ -122,6 +174,7 @@ public override void Write(byte[] buffer, int offset, int count) throw Error.NotSupported(Properties.Resources.ByteRangeStreamReadOnly); } +#if !NETSTANDARD1_3 // BeginX and EndX are not supported on Streams in netstandard1.3 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { throw Error.NotSupported(Properties.Resources.ByteRangeStreamReadOnly); @@ -131,6 +184,12 @@ public override void EndWrite(IAsyncResult asyncResult) { throw Error.NotSupported(Properties.Resources.ByteRangeStreamReadOnly); } +#endif + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + throw Error.NotSupported(Properties.Resources.ByteRangeStreamReadOnly); + } public override void WriteByte(byte value) { @@ -138,27 +197,38 @@ public override void WriteByte(byte value) } /// - /// Gets the + /// Gets the correct count for the next read operation. /// /// The count requested to be read by the caller. /// The remaining bytes to read within the range defined for this stream. private int PrepareStreamForRangeRead(int count) { - long effectiveCount = Math.Min(count, _totalCount - _currentCount); - if (effectiveCount > 0) + // A negative count causes base.Raad* methods to throw an ArgumentOutOfRangeException. + if (count <= 0) { - // Check if we should update the stream position - long position = InnerStream.Position; - if (_lowerbounds + _currentCount != position) - { - InnerStream.Position = _lowerbounds + _currentCount; - } + return count; + } - // Update current number of bytes read - _currentCount += effectiveCount; + // Reading past the end simply does nothing. + if (_currentCount >= _totalCount) + { + return 0; } - // Effective count can never be bigger than int + long effectiveCount = Math.Min(count, _totalCount - _currentCount); + + // Check if we should update the inner stream's position. + var newPosition = _lowerbounds + _currentCount; + var position = InnerStream.Position; + if (newPosition != position) + { + InnerStream.Position = newPosition; + } + + // Update current number of bytes read. + _currentCount += effectiveCount; + + // Effective count can never be bigger than int. return (int)effectiveCount; } } diff --git a/src/System.Net.Http.Formatting/Internal/DelegatingStream.cs b/src/System.Net.Http.Formatting/Internal/DelegatingStream.cs index 9547b6704..0e713fdfd 100644 --- a/src/System.Net.Http.Formatting/Internal/DelegatingStream.cs +++ b/src/System.Net.Http.Formatting/Internal/DelegatingStream.cs @@ -9,12 +9,12 @@ namespace System.Net.Http.Internal { /// - /// Stream that delegates to inner stream. + /// Stream that delegates to inner stream. /// This is taken from System.Net.Http /// internal abstract class DelegatingStream : Stream { - private Stream _innerStream; + private readonly Stream _innerStream; protected DelegatingStream(Stream innerStream) { @@ -97,7 +97,7 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel return _innerStream.ReadAsync(buffer, offset, count, cancellationToken); } -#if !NETFX_CORE // BeginX and EndX not supported on Streams in portable libraries +#if !NETSTANDARD1_3 // BeginX and EndX not supported on Streams in netstandard1.3 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return _innerStream.BeginRead(buffer, offset, count, callback, state); @@ -119,11 +119,6 @@ public override void Flush() _innerStream.Flush(); } - public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) - { - return _innerStream.CopyToAsync(destination, bufferSize, cancellationToken); - } - public override Task FlushAsync(CancellationToken cancellationToken) { return _innerStream.FlushAsync(cancellationToken); @@ -144,7 +139,7 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return _innerStream.WriteAsync(buffer, offset, count, cancellationToken); } -#if !NETFX_CORE // BeginX and EndX not supported on Streams in portable libraries +#if !NETSTANDARD1_3 // BeginX and EndX not supported on Streams in netstandard1.3 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return _innerStream.BeginWrite(buffer, offset, count, callback, state); diff --git a/src/System.Net.Http.Formatting/Internal/HttpValueCollection.cs b/src/System.Net.Http.Formatting/Internal/HttpValueCollection.cs index 1af77650e..082b33319 100644 --- a/src/System.Net.Http.Formatting/Internal/HttpValueCollection.cs +++ b/src/System.Net.Http.Formatting/Internal/HttpValueCollection.cs @@ -1,14 +1,6 @@ // 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. -#if NETFX_CORE -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Linq; -using System.Text; -using System.Web.Http; -#else using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics.Contracts; @@ -17,45 +9,29 @@ using System.Runtime.Serialization; using System.Text; using System.Web.Http; -#endif -#if NETFX_CORE -namespace System.Net.Http.Formatting -#else namespace System.Net.Http.Formatting.Internal -#endif { /// /// NameValueCollection to represent form data and to generate form data output. /// -#if NETFX_CORE - public class HttpValueCollection : IEnumerable> -#else +#if !NETSTANDARD1_3 // NameValueCollection is not serializable in netstandard1.3. [Serializable] - internal class HttpValueCollection : NameValueCollection #endif + internal class HttpValueCollection : NameValueCollection { -#if NETFX_CORE - internal readonly HashSet Names = new HashSet(StringComparer.OrdinalIgnoreCase); - internal readonly List> List = new List>(); - - /// - /// Creates a new instance - /// - public HttpValueCollection() - { - } -#else +#if !NETSTANDARD1_3 // NameValueCollection is not serializable in netstandard1.3. protected HttpValueCollection(SerializationInfo info, StreamingContext context) : base(info, context) { } +#endif private HttpValueCollection() : base(StringComparer.OrdinalIgnoreCase) // case-insensitive keys { } -#endif + // Use a builder function instead of a ctor to avoid virtual calls from the ctor. // The above condition is only important in the Full .NET fx implementation. internal static HttpValueCollection Create() @@ -75,9 +51,8 @@ internal static HttpValueCollection Create(IEnumerable /// The name to be added as a case insensitive string. /// The value to be added. - public -#if !NETFX_CORE - override -#endif - void Add(string name, string value) + public override void Add(string name, string value) { ThrowIfMaxHttpCollectionKeysExceeded(Count); name = name ?? String.Empty; value = value ?? String.Empty; -#if NETFX_CORE - Names.Add(name); - List.Add(new KeyValuePair(name, value)); -#else base.Add(name, value); -#endif } /// @@ -131,11 +97,7 @@ private string ToString(bool urlEncode) StringBuilder builder = new StringBuilder(); bool first = true; -#if NETFX_CORE - foreach (string name in Names) -#else foreach (string name in this) -#endif { string[] values = GetValues(name); if (values == null || values.Length == 0) @@ -157,10 +119,10 @@ private string ToString(bool urlEncode) private static bool AppendNameValuePair(StringBuilder builder, bool first, bool urlEncode, string name, string value) { string effectiveName = name ?? String.Empty; - string encodedName = urlEncode ? UriQueryUtility.UrlEncode(effectiveName) : effectiveName; + string encodedName = urlEncode ? WebUtility.UrlEncode(effectiveName) : effectiveName; string effectiveValue = value ?? String.Empty; - string encodedValue = urlEncode ? UriQueryUtility.UrlEncode(effectiveValue) : effectiveValue; + string encodedValue = urlEncode ? WebUtility.UrlEncode(effectiveValue) : effectiveValue; if (first) { @@ -179,104 +141,5 @@ private static bool AppendNameValuePair(StringBuilder builder, bool first, bool } return first; } - -#if NETFX_CORE - /// - /// Gets the values associated with the specified name - /// combined into one comma-separated list. - /// - /// The name of the entry that contains the values to get. The name can be null. - /// A that contains a comma-separated list of url encoded values associated - /// with the specified name if found; otherwise, null. The values are Url encoded. - public string this[string name] - { - get - { - return Get(name); - } - } - - /// - /// Gets the number of names in the collection. - /// - public int Count - { - get - { - return Names.Count; - } - } - - /// - /// Gets the values associated with the specified name - /// combined into one comma-separated list. - /// - /// The name of the entry that contains the values to get. The name can be null. - /// - /// A that contains a comma-separated list of url encoded values associated - /// with the specified name if found; otherwise, null. The values are Url encoded. - /// - public string Get(string name) - { - name = name ?? String.Empty; - - if (!Names.Contains(name)) - { - return null; - } - - List values = GetValuesInternal(name); - Contract.Assert(values != null && values.Count > 0); - - return String.Join(",", values); - } - - /// - /// Gets the values associated with the specified name. - /// - /// The - /// A that contains url encoded values associated with the name, or null if the name does not exist. - public string[] GetValues(string name) - { - name = name ?? String.Empty; - - if (!Names.Contains(name)) - { - return null; - } - - return GetValuesInternal(name).ToArray(); - } - - // call this when only when there are values available. - private List GetValuesInternal(string name) - { - List values = new List(); - - for (int i = 0; i < List.Count; i++) - { - KeyValuePair kvp = List[i]; - - if (String.Equals(kvp.Key, name, StringComparison.OrdinalIgnoreCase)) - { - values.Add(kvp.Value); - } - } - - return values; - } - - /// - public IEnumerator> GetEnumerator() - { - return List.GetEnumerator(); - } - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return List.GetEnumerator(); - } -#endif } } diff --git a/src/System.Net.Http.Formatting/Internal/NonClosingDelegatingStream.cs b/src/System.Net.Http.Formatting/Internal/NonClosingDelegatingStream.cs index 5af2385b0..1d7599654 100644 --- a/src/System.Net.Http.Formatting/Internal/NonClosingDelegatingStream.cs +++ b/src/System.Net.Http.Formatting/Internal/NonClosingDelegatingStream.cs @@ -8,8 +8,8 @@ namespace System.Net.Http.Internal /// /// Stream that doesn't close the inner stream when closed. This is to work around a limitation /// in the insisting of closing the inner stream. - /// The regular does allow for not closing the inner stream but that - /// doesn't have the quota that we need for security reasons. Implementations of + /// The regular does allow for not closing the inner stream but that + /// doesn't have the quota that we need for security reasons. Implementations of /// /// should not close the input stream when reading or writing so hence this workaround. /// @@ -20,8 +20,14 @@ public NonClosingDelegatingStream(Stream innerStream) { } +#if NETSTANDARD1_3 + protected override void Dispose(bool disposing) + { + } +#else public override void Close() { } +#endif } } diff --git a/src/System.Net.Http.Formatting/Internal/NullableAttributes.cs b/src/System.Net.Http.Formatting/Internal/NullableAttributes.cs new file mode 100644 index 000000000..2344a2994 --- /dev/null +++ b/src/System.Net.Http.Formatting/Internal/NullableAttributes.cs @@ -0,0 +1,198 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// From https://github.com/dotnet/runtime/blob/88868b7a781f4e5b9037b8721f30440207a7aa42/src/tools/illink/src/ILLink.RoslynAnalyzer/NullableAttributes.cs + +namespace System.Diagnostics.CodeAnalysis +{ +#if !NETSTANDARD2_1 + /// Specifies that null is allowed as an input even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class AllowNullAttribute : Attribute { } + + /// Specifies that null is disallowed as an input even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DisallowNullAttribute : Attribute { } + + /// Specifies that an output may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MaybeNullAttribute : Attribute { } + + /// Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns. + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullAttribute : Attribute { } + + /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MaybeNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// + public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + public bool ReturnValue { get; } + } + + /// Specifies that the output will be non-null if the named parameter is non-null. + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class NotNullIfNotNullAttribute : Attribute + { + /// Initializes the attribute with the associated parameter name. + /// + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// + public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// Gets the associated parameter name. + public string ParameterName { get; } + } + + /// Applied to a method that will never return under any circumstance. + [AttributeUsage(AttributeTargets.Method, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DoesNotReturnAttribute : Attribute { } + + /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class DoesNotReturnIfAttribute : Attribute + { + /// Initializes the attribute with the specified parameter value. + /// + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// + public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// Gets the condition parameter value. + public bool ParameterValue { get; } + } +#endif + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MemberNotNullAttribute : Attribute + { + /// Initializes the attribute with a field or property member. + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullAttribute(string member) => Members = new[] { member }; + + /// Initializes the attribute with the list of field and property members. + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullAttribute(params string[] members) => Members = members; + + /// Gets field or property member names. + public string[] Members { get; } + } + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class MemberNotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition and a field or property member. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new[] { member }; + } + + /// Initializes the attribute with the specified return value condition and list of field and property members. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// Gets the return value condition. + public bool ReturnValue { get; } + + /// Gets field or property member names. + public string[] Members { get; } + } +} diff --git a/src/System.Net.Http.Formatting/Internal/ReadOnlyStreamWithEncodingPreamble.cs b/src/System.Net.Http.Formatting/Internal/ReadOnlyStreamWithEncodingPreamble.cs deleted file mode 100644 index 923e4bd37..000000000 --- a/src/System.Net.Http.Formatting/Internal/ReadOnlyStreamWithEncodingPreamble.cs +++ /dev/null @@ -1,175 +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. - -using System.Diagnostics.Contracts; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace System.Net.Http.Internal -{ - /// - /// This implements a read-only, forward-only stream around another readable stream, to ensure - /// that there is an appropriate encoding preamble in the stream. - /// - internal class ReadOnlyStreamWithEncodingPreamble : Stream - { - private static Task _cancelledTask = GetCancelledTask(); - private Stream _innerStream; - private ArraySegment _remainingBytes; - - public ReadOnlyStreamWithEncodingPreamble(Stream innerStream, Encoding encoding) - { - Contract.Assert(innerStream != null); - Contract.Assert(innerStream.CanRead); - Contract.Assert(encoding != null); - - _innerStream = innerStream; - - // Determine whether we even have a preamble to be concerned about - byte[] preamble = encoding.GetPreamble(); - int preambleLength = preamble.Length; - if (preambleLength <= 0) - { - return; - } - - // Create a double sized buffer, and read enough bytes from the stream to know - // whether we have a preamble present already or not. - int finalBufferLength = preambleLength * 2; - byte[] finalBuffer = new byte[finalBufferLength]; - int finalCount = preambleLength; - preamble.CopyTo(finalBuffer, 0); - - // Read the first bytes of the stream and see if they already contain a preamble - for (; finalCount < finalBufferLength; finalCount++) - { - int b = innerStream.ReadByte(); - if (b == -1) - { - break; - } - finalBuffer[finalCount] = (byte)b; - } - - // Did we read enough bytes to do the comparison? - if (finalCount == finalBufferLength) - { - bool foundPreamble = true; - for (int idx = 0; idx < preambleLength; idx++) - { - if (finalBuffer[idx] != finalBuffer[idx + preambleLength]) - { - foundPreamble = false; - break; - } - } - - // If we found the preamble, then just exclude it from the data that we return - if (foundPreamble) - { - finalCount = preambleLength; - } - } - - _remainingBytes = new ArraySegment(finalBuffer, 0, finalCount); - } - - public override bool CanRead - { - get { return true; } - } - - public override bool CanSeek - { - get { return false; } - } - - public override bool CanWrite - { - get { return false; } - } - - public override long Length - { - get { throw new NotImplementedException(); } - } - - public override long Position - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - public override void Flush() - { - throw new NotImplementedException(); - } - - private static Task GetCancelledTask() - { - var tcs = new TaskCompletionSource(); - tcs.SetCanceled(); - return tcs.Task; - } - - public override int Read(byte[] buffer, int offset, int count) - { - byte[] remainingArray = _remainingBytes.Array; - if (remainingArray == null) - { - return _innerStream.Read(buffer, offset, count); - } - - int remainingCount = _remainingBytes.Count; - int remainingOffset = _remainingBytes.Offset; - int result = Math.Min(count, remainingCount); - - for (int idx = 0; idx < result; ++idx) - { - buffer[offset + idx] = remainingArray[remainingOffset + idx]; - } - - if (result == remainingCount) - { - _remainingBytes = default(ArraySegment); - } - else - { - _remainingBytes = new ArraySegment(remainingArray, remainingOffset + result, remainingCount - result); - } - - return result; - } - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - if (_remainingBytes.Array == null) - { - return _innerStream.ReadAsync(buffer, offset, count, cancellationToken); - } - if (cancellationToken.IsCancellationRequested) - { - return _cancelledTask; - } - - return Task.FromResult(Read(buffer, offset, count)); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotImplementedException(); - } - - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/System.Net.Http.Formatting/Internal/TranscodingStream.cs b/src/System.Net.Http.Formatting/Internal/TranscodingStream.cs new file mode 100644 index 000000000..f279b73ad --- /dev/null +++ b/src/System.Net.Http.Formatting/Internal/TranscodingStream.cs @@ -0,0 +1,828 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// From https://github.com/dotnet/runtime/blob/88868b7a781f4e5b9037b8721f30440207a7aa42/src/libraries/System.Private.CoreLib/src/System/Text/TranscodingStream.cs + +using System.Buffers; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http; +using Properties = System.Net.Http.Properties; + +#nullable enable + +namespace System.Text +{ + internal sealed class TranscodingStream : Stream + { + private const int DefaultReadByteBufferSize = 4 * 1024; // lifted from StreamReader.cs (FileStream) + + // We optimistically assume 1 byte ~ 1 char during transcoding. This is a good rule of thumb + // but isn't always appropriate: transcoding between single-byte and multi-byte encodings + // will violate this, as will any invalid data fixups performed by the transcoder itself. + // To account for these unknowns we have a minimum scratch buffer size we use during the + // transcoding process. This should be generous enough to account for even the largest + // fallback mechanism we're likely to see in the real world. + + private const int MinWriteRentedArraySize = 4 * 1024; + private const int MaxWriteRentedArraySize = 1024 * 1024; + + private static readonly byte[] EmptyByteBuffer = new byte[0]; + private static readonly char[] EmptyCharBuffer = new char[0]; + + private readonly Encoding _innerEncoding; + private readonly Encoding _thisEncoding; + private Stream _innerStream; // null if the wrapper has been disposed + private readonly bool _leaveOpen; + private readonly byte[] _singleByteBuffer = new byte[1]; + + /* + * Fields used for writing bytes [this] -> chars -> bytes [inner] + * Lazily initialized the first time we need to write + */ + + private Encoder? _innerEncoder; + private Decoder? _thisDecoder; + + /* + * Fields used for reading bytes [inner] -> chars -> bytes [this] + * Lazily initialized the first time we need to read + */ + + private Encoder? _thisEncoder; + private Decoder? _innerDecoder; + private int _readCharBufferMaxSize; // the maximum number of characters _innerDecoder.ReadChars can return + private byte[]? _readBuffer; // contains the data that Read() should return + private int _readBufferOffset; + private int _readBufferCount; + + internal TranscodingStream(Stream innerStream, Encoding innerEncoding, Encoding thisEncoding, bool leaveOpen = false) + { + _innerStream = innerStream ?? throw Error.ArgumentNull(nameof(innerStream)); + _leaveOpen = leaveOpen; + + _innerEncoding = innerEncoding ?? throw Error.ArgumentNull(nameof(innerEncoding)); + _thisEncoding = thisEncoding ?? throw Error.ArgumentNull(nameof(thisEncoding)); + } + + /* + * Most CanXyz methods delegate to the inner stream, returning false + * if this instance has been disposed. CanSeek is always false. + */ + + public override bool CanRead => _innerStream?.CanRead ?? false; + + public override bool CanSeek => false; + + public override bool CanWrite => _innerStream?.CanWrite ?? false; + + public override long Length => throw Error.NotSupported(Properties.Resources.NotSupported_UnseekableStream); + + public override long Position + { + get => throw Error.NotSupported(Properties.Resources.NotSupported_UnseekableStream); + set => throw Error.NotSupported(Properties.Resources.NotSupported_UnseekableStream); + } + + protected override void Dispose(bool disposing) + { + Debug.Assert(disposing, "This type isn't finalizable."); + base.Dispose(disposing); + + if (_innerStream is null) + { + return; // dispose called multiple times, ignore + } + + // First, flush any pending data to the inner stream. + + ArraySegment pendingData = FinalFlushWriteBuffers(); + if (pendingData.Count != 0) + { + _innerStream.Write(pendingData.Array, pendingData.Offset, pendingData.Count); + } + + // Mark our object as disposed + + Stream innerStream = _innerStream; + _innerStream = null!; + + // And dispose the inner stream if needed + + if (!_leaveOpen) + { + innerStream.Dispose(); + } + } + +#if NETCOREAPP3_1_OR_GREATER || NETSTANDARD2_1 + public override ValueTask DisposeAsync() + { + if (_innerStream is null) + { + return default; // dispose called multiple times, ignore + } + + // First, get any pending data destined for the inner stream. + + ArraySegment pendingData = FinalFlushWriteBuffers(); + + if (pendingData.Count == 0) + { + // Fast path: just dispose of the object graph. + // No need to write anything to the stream first. + + Stream innerStream = _innerStream; + _innerStream = null!; + + return (_leaveOpen) + ? default /* no work to do */ + : innerStream.DisposeAsync(); + } + + // Slower path; need to perform an async write followed by an async dispose. + + return DisposeAsyncCore(pendingData); + async ValueTask DisposeAsyncCore(ArraySegment pendingData) + { + Debug.Assert(pendingData.Count != 0); + + Stream innerStream = _innerStream; + _innerStream = null!; + + await innerStream.WriteAsync(pendingData.AsMemory()).ConfigureAwait(false); + + if (!_leaveOpen) + { + await innerStream.DisposeAsync().ConfigureAwait(false); + } + } + } +#endif + +#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant +#pragma warning disable CS8774 // Member must have a non-null value when exiting. + + // Sets up the data structures that are necessary before any read operation takes place, + // throwing if the object is in a state where reads are not possible. + [MemberNotNull(nameof(_innerDecoder), nameof(_thisEncoder), nameof(_readBuffer))] + private void EnsurePreReadConditions() + { + ThrowIfDisposed(); + if (_innerDecoder is null) + { + InitializeReadDataStructures(); + } + + void InitializeReadDataStructures() + { + if (!CanRead) + { + throw Error.NotSupported(Properties.Resources.NotSupported_UnreadableStream); + } + + _innerDecoder = _innerEncoding.GetDecoder(); + _thisEncoder = _thisEncoding.GetEncoder(); + _readCharBufferMaxSize = _innerEncoding.GetMaxCharCount(DefaultReadByteBufferSize); + + // Can't use ArrayPool for the below array since it's an instance field of this object. + // But since we never expose the raw array contents to our callers we can get away + // with skipping the array zero-init during allocation. The segment points to the + // data which we haven't yet read; however, we own the entire backing array and can + // re-create the segment as needed once the array is repopulated. + +#if NET5_0_OR_GREATER + _readBuffer = GC.AllocateUninitializedArray(_thisEncoding.GetMaxByteCount(_readCharBufferMaxSize)); +#else + _readBuffer = new byte[_thisEncoding.GetMaxByteCount(_readCharBufferMaxSize)]; +#endif + } + } + + // Sets up the data structures that are necessary before any write operation takes place, + // throwing if the object is in a state where writes are not possible. + [MemberNotNull(nameof(_thisDecoder), nameof(_innerEncoder))] + private void EnsurePreWriteConditions() + { + ThrowIfDisposed(); + if (_innerEncoder is null) + { + InitializeReadDataStructures(); + } + + void InitializeReadDataStructures() + { + if (!CanWrite) + { + throw Error.NotSupported(Properties.Resources.NotSupported_UnwritableStream); + } + + _innerEncoder = _innerEncoding.GetEncoder(); + _thisDecoder = _thisEncoding.GetDecoder(); + } + } + +#pragma warning restore CS8774 // Member must have a non-null value when exiting. +#pragma warning restore CS3016 // Arrays as attribute arguments is not CLS-compliant + + // returns any pending data that needs to be flushed to the inner stream before disposal + private ArraySegment FinalFlushWriteBuffers() + { + // If this stream was never used for writing, no-op. + + if (_thisDecoder is null || _innerEncoder is null) + { + return default; + } + + // convert bytes [this] -> chars + // Having leftover data in our buffers should be very rare since it should only + // occur if the end of the stream contains an incomplete multi-byte sequence. + // Let's not bother complicating this logic with array pool rentals or allocation- + // avoiding loops. + + char[] chars = EmptyCharBuffer; + int charCount = _thisDecoder.GetCharCount(EmptyByteBuffer, 0, 0, flush: true); + if (charCount > 0) + { + chars = new char[charCount]; + charCount = _thisDecoder.GetChars(EmptyByteBuffer, 0, 0, chars, 0, flush: true); + } + + // convert chars -> bytes [inner] + // It's possible that _innerEncoder might need to perform some end-of-text fixup + // (due to flush: true), even if _thisDecoder didn't need to do so. + + byte[] bytes = EmptyByteBuffer; + int byteCount = _innerEncoder.GetByteCount(chars, 0, charCount, flush: true); + if (byteCount > 0) + { + bytes = new byte[byteCount]; + byteCount = _innerEncoder.GetBytes(chars, 0, charCount, bytes, 0, flush: true); + } + + return new ArraySegment(bytes, 0, byteCount); + } + + public override void Flush() + { + // Don't pass flush: true to our inner decoder + encoder here, since it could cause data + // corruption if a flush occurs mid-stream. Wait until the stream is being closed. + + ThrowIfDisposed(); + _innerStream.Flush(); + } + + public override Task FlushAsync(CancellationToken cancellationToken) + { + // Don't pass flush: true to our inner decoder + encoder here, since it could cause data + // corruption if a flush occurs mid-stream. Wait until the stream is being closed. + + ThrowIfDisposed(); + return _innerStream.FlushAsync(cancellationToken); + } + + public override int Read(byte[] buffer, int offset, int count) + { + ValidateBufferArguments(buffer, offset, count); + + return Read(new Span(buffer, offset, count)); + } + +#if NETCOREAPP || NETSTANDARD2_1 + public override +#else + private +#endif + int Read(Span buffer) + { + EnsurePreReadConditions(); + + // If there's no data in our pending read buffer, we'll need to populate it from + // the inner stream. We read the inner stream's bytes, decode that to chars using + // the 'inner' encoding, then re-encode those chars under the 'this' encoding. + // We've already calculated the worst-case expansions for the intermediate buffers, + // so we use GetChars / GetBytes instead of Convert to simplify the below code + // and to ensure an exception is thrown if the Encoding reported an incorrect + // worst-case expansion. + + if (_readBufferCount == 0) + { + byte[] rentedBytes = ArrayPool.Shared.Rent(DefaultReadByteBufferSize); + char[] rentedChars = ArrayPool.Shared.Rent(_readCharBufferMaxSize); + + try + { + int pendingReadDataPopulatedJustNow; + bool isEofReached; + + do + { + // Beware: Use our constant value instead of 'rentedBytes.Length' for the count + // parameter below. The reason for this is that the array pool could've returned + // a larger-than-expected array, but our worst-case expansion calculations + // performed earlier didn't take that into account. + + int innerBytesReadJustNow = _innerStream.Read(rentedBytes, 0, DefaultReadByteBufferSize); + isEofReached = (innerBytesReadJustNow == 0); + + // Convert bytes [inner] -> chars, then convert chars -> bytes [this]. + // We can't return 0 to our caller until inner stream EOF has been reached. But if the + // inner stream returns a non-empty but incomplete buffer, GetBytes may return 0 anyway + // since it can't yet make forward progress on the input data. If this happens, we'll + // loop so that we don't return 0 to our caller until we truly see inner stream EOF. + + int charsDecodedJustNow = _innerDecoder.GetChars(rentedBytes, 0, innerBytesReadJustNow, rentedChars, 0, flush: isEofReached); + pendingReadDataPopulatedJustNow = _thisEncoder.GetBytes(rentedChars, 0, charsDecodedJustNow, _readBuffer, 0, flush: isEofReached); + } while (!isEofReached && pendingReadDataPopulatedJustNow == 0); + + _readBufferOffset = 0; + _readBufferCount = pendingReadDataPopulatedJustNow; + } + finally + { + ArrayPool.Shared.Return(rentedBytes); + ArrayPool.Shared.Return(rentedChars); + } + } + + // At this point: (a) we've populated our pending read buffer and there's + // useful data to return to our caller; or (b) the pending read buffer is + // empty because the inner stream has reached EOF and all pending read data + // has already been flushed, and we should return 0. + + int bytesToReturn = Math.Min(_readBufferCount, buffer.Length); + _readBuffer.AsSpan(_readBufferOffset, bytesToReturn).CopyTo(buffer); + _readBufferOffset += bytesToReturn; + _readBufferCount -= bytesToReturn; + return bytesToReturn; + } + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + ValidateBufferArguments(buffer, offset, count); + + return ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); + } + +#if NETCOREAPP || NETSTANDARD2_1 + public override +#else + private +#endif + ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + { + EnsurePreReadConditions(); + + if (cancellationToken.IsCancellationRequested) + { +#if NETCOREAPP || NETSTANDARD + return new ValueTask(Task.FromCanceled(cancellationToken)); +#else + // Lose track of the CancellationToken in this case. + return new ValueTask(TaskHelpers.Canceled()); +#endif + } + + return ReadAsyncCore(buffer, cancellationToken); + async ValueTask ReadAsyncCore(Memory buffer, CancellationToken cancellationToken) + { + // If there's no data in our pending read buffer, we'll need to populate it from + // the inner stream. We read the inner stream's bytes, decode that to chars using + // the 'inner' encoding, then re-encode those chars under the 'this' encoding. + // We've already calculated the worst-case expansions for the intermediate buffers, + // so we use GetChars / GetBytes instead of Convert to simplify the below code + // and to ensure an exception is thrown if the Encoding reported an incorrect + // worst-case expansion. + + if (_readBufferCount == 0) + { + byte[] rentedBytes = ArrayPool.Shared.Rent(DefaultReadByteBufferSize); + char[] rentedChars = ArrayPool.Shared.Rent(_readCharBufferMaxSize); + + try + { + int pendingReadDataPopulatedJustNow; + bool isEofReached; + + do + { + // Beware: Use our constant value instead of 'rentedBytes.Length' when creating + // the Mem struct. The reason for this is that the array pool could've returned + // a larger-than-expected array, but our worst-case expansion calculations + // performed earlier didn't take that into account. + + int innerBytesReadJustNow = await _innerStream.ReadAsync(rentedBytes, 0, DefaultReadByteBufferSize, cancellationToken).ConfigureAwait(false); + isEofReached = (innerBytesReadJustNow == 0); + + // Convert bytes [inner] -> chars, then convert chars -> bytes [this]. + // We can't return 0 to our caller until inner stream EOF has been reached. But if the + // inner stream returns a non-empty but incomplete buffer, GetBytes may return 0 anyway + // since it can't yet make forward progress on the input data. If this happens, we'll + // loop so that we don't return 0 to our caller until we truly see inner stream EOF. + + int charsDecodedJustNow = _innerDecoder.GetChars(rentedBytes, 0, innerBytesReadJustNow, rentedChars, 0, flush: isEofReached); + pendingReadDataPopulatedJustNow = _thisEncoder.GetBytes(rentedChars, 0, charsDecodedJustNow, _readBuffer, 0, flush: isEofReached); + } while (!isEofReached && pendingReadDataPopulatedJustNow == 0); + + _readBufferOffset = 0; + _readBufferCount = pendingReadDataPopulatedJustNow; + } + finally + { + ArrayPool.Shared.Return(rentedBytes); + ArrayPool.Shared.Return(rentedChars); + } + } + + // At this point: (a) we've populated our pending read buffer and there's + // useful data to return to our caller; or (b) the pending read buffer is + // empty because the inner stream has reached EOF and all pending read data + // has already been flushed, and we should return 0. + + int bytesToReturn = Math.Min(_readBufferCount, buffer.Length); + _readBuffer.AsSpan(_readBufferOffset, bytesToReturn).CopyTo(buffer.Span); + _readBufferOffset += bytesToReturn; + _readBufferCount -= bytesToReturn; + return bytesToReturn; + } + } + + public override int ReadByte() + { + return Read(_singleByteBuffer, offset: 0, count: 1) != 0 ? _singleByteBuffer[0] : -1; + } + + public override long Seek(long offset, SeekOrigin origin) + => throw Error.NotSupported(Properties.Resources.NotSupported_UnseekableStream); + + public override void SetLength(long value) + => throw Error.NotSupported(Properties.Resources.NotSupported_UnseekableStream); + +#if NET6_0_OR_GREATER + [StackTraceHidden] +#endif + private void ThrowIfDisposed() + { + if (_innerStream is null) + { + ThrowObjectDisposedException(); + } + } + + [DoesNotReturn] +#if NET6_0_OR_GREATER + [StackTraceHidden] +#endif + private void ThrowObjectDisposedException() + { + throw new ObjectDisposedException(GetType().Name, Properties.Resources.ObjectDisposed_StreamClosed); + } + + public override void Write(byte[] buffer, int offset, int count) + { + ValidateBufferArguments(buffer, offset, count); + +#if NETCOREAPP || NETSTANDARD2_1 + Write(new ReadOnlySpan(buffer, offset, count)); +#else + WriteCore(buffer, offset, count); +#endif + } + +#if NETCOREAPP || NETSTANDARD2_1 + public override void Write(ReadOnlySpan buffer) + { + EnsurePreWriteConditions(); + + if (buffer.IsEmpty) + { + return; + } + + int rentalLength = buffer.Length < MinWriteRentedArraySize ? MinWriteRentedArraySize : + buffer.Length > MaxWriteRentedArraySize ? MaxWriteRentedArraySize : + buffer.Length; + + char[] scratchChars = ArrayPool.Shared.Rent(rentalLength); + byte[] scratchBytes = ArrayPool.Shared.Rent(rentalLength); + + try + { + bool decoderFinished, encoderFinished; + do + { + // convert bytes [this] -> chars + + _thisDecoder.Convert( + bytes: buffer, + chars: scratchChars, + flush: false, + out int bytesConsumed, + out int charsWritten, + out decoderFinished); + + buffer = buffer.Slice(bytesConsumed); + + // convert chars -> bytes [inner] + + Span decodedChars = scratchChars.AsSpan(0, charsWritten); + + do + { + _innerEncoder.Convert( + chars: decodedChars, + bytes: scratchBytes, + flush: false, + out int charsConsumed, + out int bytesWritten, + out encoderFinished); + + decodedChars = decodedChars.Slice(charsConsumed); + + // It's more likely that the inner stream provides an optimized implementation of + // Write(byte[], ...) over Write(ROS), so we'll prefer the byte[]-based overloads. + + _innerStream.Write(scratchBytes, 0, bytesWritten); + } while (!encoderFinished); + } while (!decoderFinished); + } + finally + { + ArrayPool.Shared.Return(scratchChars); + ArrayPool.Shared.Return(scratchBytes); + } + } +#else + private void WriteCore(byte[] buffer, int offset, int count) + { + EnsurePreWriteConditions(); + + if (count == 0) + { + return; + } + + int rentalLength = buffer.Length < MinWriteRentedArraySize ? MinWriteRentedArraySize : + buffer.Length > MaxWriteRentedArraySize ? MaxWriteRentedArraySize : + buffer.Length; + + char[] scratchChars = ArrayPool.Shared.Rent(rentalLength); + byte[] scratchBytes = ArrayPool.Shared.Rent(rentalLength); + + try + { + bool decoderFinished, encoderFinished; + do + { + // convert bytes [this] -> chars + + _thisDecoder.Convert( + bytes: buffer, + byteIndex: offset, + byteCount: count, + chars: scratchChars, + charIndex: 0, + charCount: rentalLength, + flush: false, + out int bytesConsumed, + out int charsWritten, + out decoderFinished); + + offset += bytesConsumed; + count -= bytesConsumed; + + // convert chars -> bytes [inner] + + int scratchOffset = 0; + do + { + _innerEncoder.Convert( + chars: scratchChars, + charIndex: scratchOffset, + charCount: charsWritten, + bytes: scratchBytes, + byteIndex: 0, + byteCount: rentalLength, + flush: false, + out int charsConsumed, + out int bytesWritten, + out encoderFinished); + + scratchOffset += charsConsumed; + charsWritten -= charsConsumed; + + // It's more likely that the inner stream provides an optimized implementation of + // Write(byte[], ...) over Write(ROS), so we'll prefer the byte[]-based overloads. + + _innerStream.Write(scratchBytes, 0, bytesWritten); + } while (!encoderFinished); + } while (!decoderFinished); + } + finally + { + ArrayPool.Shared.Return(scratchChars); + ArrayPool.Shared.Return(scratchBytes); + } + } +#endif + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + ValidateBufferArguments(buffer, offset, count); + +#if NETCOREAPP || NETSTANDARD2_1 + return WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); +#else + return WriteAsyncCore(buffer, offset, count, cancellationToken).AsTask(); +#endif + } + +#if NETCOREAPP || NETSTANDARD2_1 + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + { + EnsurePreWriteConditions(); + + if (cancellationToken.IsCancellationRequested) + { + return new ValueTask(Task.FromCanceled(cancellationToken)); + } + + if (buffer.IsEmpty) + { + // ValueTask.CompletedTask + return default; + } + + return WriteAsyncCore(buffer, cancellationToken); + async ValueTask WriteAsyncCore(ReadOnlyMemory remainingOuterEncodedBytes, CancellationToken cancellationToken) + { + int rentalLength = remainingOuterEncodedBytes.Length < MinWriteRentedArraySize ? MinWriteRentedArraySize : + remainingOuterEncodedBytes.Length > MaxWriteRentedArraySize ? MaxWriteRentedArraySize: + remainingOuterEncodedBytes.Length; + + char[] scratchChars = ArrayPool.Shared.Rent(rentalLength); + byte[] scratchBytes = ArrayPool.Shared.Rent(rentalLength); + + try + { + bool decoderFinished, encoderFinished; + do + { + // convert bytes [this] -> chars + + _thisDecoder.Convert( + bytes: buffer, + chars: scratchChars, + flush: false, + out int bytesConsumed, + out int charsWritten, + out decoderFinished); + + buffer = buffer.Slice(bytesConsumed); + + // convert chars -> bytes [inner] + + Span decodedChars = scratchChars.AsSpan(0, charsWritten); + + do + { + _innerEncoder.Convert( + chars: decodedChars, + bytes: scratchBytes, + flush: false, + out int charsConsumed, + out int bytesWritten, + out encoderFinished); + + decodedChars = decodedChars.Slice(charsConsumed); + + await _innerStream.WriteAsync(scratchBytes, 0, bytesWritten, cancellationToken).ConfigureAwait(false); + } while (!encoderFinished); + } while (!decoderFinished); + } + finally + { + ArrayPool.Shared.Return(scratchChars); + ArrayPool.Shared.Return(scratchBytes); + } + } + } +#else + private ValueTask WriteAsyncCore(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + EnsurePreWriteConditions(); + + if (cancellationToken.IsCancellationRequested) + { +#if NETSTANDARD + return new ValueTask(Task.FromCanceled(cancellationToken)); +#else + // Lose track of the CancellationToken in this case. + return new ValueTask(TaskHelpers.Canceled()); +#endif + } + + if (count == 0) + { + // ValueTask.CompletedTask + return default; + } + + return WriteAsyncCore(buffer, cancellationToken); + async ValueTask WriteAsyncCore(ReadOnlyMemory remainingOuterEncodedBytes, CancellationToken cancellationToken) + { + int rentalLength = remainingOuterEncodedBytes.Length < MinWriteRentedArraySize ? MinWriteRentedArraySize : + remainingOuterEncodedBytes.Length > MaxWriteRentedArraySize ? MaxWriteRentedArraySize : + remainingOuterEncodedBytes.Length; + + char[] scratchChars = ArrayPool.Shared.Rent(rentalLength); + byte[] scratchBytes = ArrayPool.Shared.Rent(rentalLength); + + try + { + bool decoderFinished, encoderFinished; + do + { + // convert bytes [this] -> chars + + _thisDecoder.Convert( + bytes: buffer, + byteIndex: offset, + byteCount: count, + chars: scratchChars, + charIndex: 0, + charCount: rentalLength, + flush: false, + out int bytesConsumed, + out int charsWritten, + out decoderFinished); + + offset += bytesConsumed; + count -= bytesConsumed; + + // convert chars -> bytes [inner] + + int scratchOffset = 0; + do + { + _innerEncoder.Convert( + chars: scratchChars, + charIndex: scratchOffset, + charCount: charsWritten, + bytes: scratchBytes, + byteIndex: 0, + byteCount: rentalLength, + flush: false, + out int charsConsumed, + out int bytesWritten, + out encoderFinished); + + scratchOffset += charsConsumed; + charsWritten -= charsConsumed; + + await _innerStream.WriteAsync(scratchBytes, 0, bytesWritten, cancellationToken).ConfigureAwait(false); + } while (!encoderFinished); + } while (!decoderFinished); + } + finally + { + ArrayPool.Shared.Return(scratchChars); + ArrayPool.Shared.Return(scratchBytes); + } + } + } +#endif + + public override void WriteByte(byte value) + { + _singleByteBuffer[0] = value; + Write(_singleByteBuffer, offset: 0, count: 1); + } + + // From https://github.com/dotnet/runtime/blob/88868b7a781f4e5b9037b8721f30440207a7aa42/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void ValidateBufferArguments(byte[] buffer, int offset, int count) + { + if (buffer is null) + { + throw Error.ArgumentNull(nameof(buffer)); + } + + if (offset < 0) + { + throw Error.ArgumentMustBeGreaterThanOrEqualTo(nameof(offset), offset, minValue: 0); + } + + if ((uint)count > buffer.Length - offset) + { + throw Error.ArgumentOutOfRange(nameof(count), count, Properties.Resources.Argument_InvalidOffLen); + } + } + } +} diff --git a/src/System.Net.Http.Formatting/Internal/TypeExtensions.cs b/src/System.Net.Http.Formatting/Internal/TypeExtensions.cs index 0f22bfcea..aab7ca05c 100644 --- a/src/System.Net.Http.Formatting/Internal/TypeExtensions.cs +++ b/src/System.Net.Http.Formatting/Internal/TypeExtensions.cs @@ -8,7 +8,7 @@ namespace System.Net.Http { internal static class TypeExtensions { -#if NETFX_CORE +#if NETSTANDARD1_3 private static bool EqualTo(this Type[] t1, Type[] t2) { if (t1.Length != t2.Length) @@ -42,7 +42,7 @@ public static Type ExtractGenericInterface(this Type queryType, Type interfaceTy return (matchesInterface(queryType)) ? queryType : queryType.GetInterfaces().FirstOrDefault(matchesInterface); } -#if NETFX_CORE +#if NETSTANDARD1_3 public static Type[] GetGenericArguments(this Type type) { return type.GetTypeInfo().GenericTypeArguments; @@ -54,7 +54,7 @@ public static Type[] GetInterfaces(this Type type) } #endif -#if NETFX_CORE +#if NETSTANDARD1_3 public static bool IsAssignableFrom(this Type type, Type c) { return type.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo()); @@ -63,7 +63,7 @@ public static bool IsAssignableFrom(this Type type, Type c) public static bool IsGenericType(this Type type) { -#if NETFX_CORE +#if NETSTANDARD1_3 return type.GetTypeInfo().IsGenericType; #else return type.IsGenericType; @@ -72,7 +72,7 @@ public static bool IsGenericType(this Type type) public static bool IsInterface(this Type type) { -#if NETFX_CORE +#if NETSTANDARD1_3 return type.GetTypeInfo().IsInterface; #else return type.IsInterface; @@ -81,7 +81,7 @@ public static bool IsInterface(this Type type) public static bool IsValueType(this Type type) { -#if NETFX_CORE +#if NETSTANDARD1_3 return type.GetTypeInfo().IsValueType; #else return type.IsValueType; diff --git a/src/System.Net.Http.Formatting/InvalidByteRangeException.cs b/src/System.Net.Http.Formatting/InvalidByteRangeException.cs index 230564dbd..ef6175208 100644 --- a/src/System.Net.Http.Formatting/InvalidByteRangeException.cs +++ b/src/System.Net.Http.Formatting/InvalidByteRangeException.cs @@ -9,7 +9,7 @@ namespace System.Net.Http { /// - /// An exception thrown by in case none of the requested ranges + /// An exception thrown by in case none of the requested ranges /// overlap with the current extend of the selected resource. The current extend of the resource /// is indicated in the ContentRange property. /// @@ -35,11 +35,13 @@ public InvalidByteRangeException(ContentRangeHeaderValue contentRange, string me Initialize(contentRange); } +#if !NETSTANDARD1_3 // Exception is not serializable in netstandard1.3. public InvalidByteRangeException(ContentRangeHeaderValue contentRange, SerializationInfo info, StreamingContext context) : base(info, context) { Initialize(contentRange); } +#endif /// /// The current extend of the resource indicated in terms of a ContentRange header field. diff --git a/src/System.Net.Http.Formatting/MimeBodyPart.cs b/src/System.Net.Http.Formatting/MimeBodyPart.cs index aa14f5dc6..cd07e8bba 100644 --- a/src/System.Net.Http.Formatting/MimeBodyPart.cs +++ b/src/System.Net.Http.Formatting/MimeBodyPart.cs @@ -39,8 +39,8 @@ public MimeBodyPart(MultipartStreamProvider streamProvider, int maxBodyPartHeade Segments = new List>(2); _headers = FormattingUtilities.CreateEmptyContentHeaders(); HeaderParser = new InternetMessageFormatHeaderParser( - _headers, - maxBodyPartHeaderSize, + _headers, + maxBodyPartHeaderSize, ignoreHeaderValidation: true); } @@ -190,7 +190,7 @@ private void CleanupOutputStream() } else { -#if NETFX_CORE +#if NETSTANDARD1_3 _outputStream.Dispose(); #else _outputStream.Close(); diff --git a/src/System.Net.Http.Formatting/MultipartFormDataStreamProvider.cs b/src/System.Net.Http.Formatting/MultipartFormDataStreamProvider.cs index f2c997e92..1e012106b 100644 --- a/src/System.Net.Http.Formatting/MultipartFormDataStreamProvider.cs +++ b/src/System.Net.Http.Formatting/MultipartFormDataStreamProvider.cs @@ -11,12 +11,12 @@ namespace System.Net.Http { /// - /// A implementation suited for use with HTML file uploads for writing file - /// content to a . The stream provider looks at the Content-Disposition header + /// A implementation suited for use with HTML file uploads for writing file + /// content to a . The stream provider looks at the Content-Disposition header /// field and determines an output based on the presence of a filename parameter. - /// If a filename parameter is present in the Content-Disposition header field then the body + /// If a filename parameter is present in the Content-Disposition header field then the body /// part is written to a , otherwise it is written to a . - /// This makes it convenient to process MIME Multipart HTML Form data which is a combination of form + /// This makes it convenient to process MIME Multipart HTML Form data which is a combination of form /// data and file content. /// public class MultipartFormDataStreamProvider : MultipartFileStreamProvider @@ -52,7 +52,7 @@ public MultipartFormDataStreamProvider(string rootPath, int bufferSize) /// /// This body part stream provider examines the headers provided by the MIME multipart parser - /// and decides whether it should return a file stream or a memory stream for the body part to be + /// and decides whether it should return a file stream or a memory stream for the body part to be /// written to. /// /// The parent MIME multipart HttpContent instance. diff --git a/src/System.Net.Http.Formatting/MultipartRelatedStreamProvider.cs b/src/System.Net.Http.Formatting/MultipartRelatedStreamProvider.cs index 464f891e7..68b5a6034 100644 --- a/src/System.Net.Http.Formatting/MultipartRelatedStreamProvider.cs +++ b/src/System.Net.Http.Formatting/MultipartRelatedStreamProvider.cs @@ -24,7 +24,7 @@ public class MultipartRelatedStreamProvider : MultipartStreamProvider private HttpContent _parent; /// - /// Gets the instance that has been marked as the root content in the + /// Gets the instance that has been marked as the root content in the /// MIME multipart related message using the start parameter. If no start parameter is /// present then pick the first of the children. /// @@ -71,7 +71,7 @@ private static HttpContent FindRootContent(HttpContent parent, IEnumerable /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -19,19 +20,19 @@ namespace System.Net.Http.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { - + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -39,7 +40,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { -#if NETFX_CORE +#if NETSTANDARD1_3 var assembly = typeof(Resources).GetTypeInfo().Assembly; #else var assembly = typeof(Resources).Assembly; @@ -50,7 +51,7 @@ internal Resources() { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -64,7 +65,16 @@ internal Resources() { resourceCulture = value; } } - + + /// + /// Looks up a localized string similar to Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.. + /// + internal static string Argument_InvalidOffLen { + get { + return ResourceManager.GetString("Argument_InvalidOffLen", resourceCulture); + } + } + /// /// Looks up a localized string similar to Async Callback threw an exception.. /// @@ -73,7 +83,7 @@ internal static string AsyncResult_CallbackThrewException { return ResourceManager.GetString("AsyncResult_CallbackThrewException", resourceCulture); } } - + /// /// Looks up a localized string similar to The IAsyncResult implementation '{0}' tried to complete a single operation multiple times. This could be caused by an incorrect application IAsyncResult implementation or other extensibility code, such as an IAsyncResult that returns incorrect CompletedSynchronously values or invokes the AsyncCallback multiple times.. /// @@ -82,7 +92,7 @@ internal static string AsyncResult_MultipleCompletes { return ResourceManager.GetString("AsyncResult_MultipleCompletes", resourceCulture); } } - + /// /// Looks up a localized string similar to End cannot be called twice on an AsyncResult.. /// @@ -91,7 +101,7 @@ internal static string AsyncResult_MultipleEnds { return ResourceManager.GetString("AsyncResult_MultipleEnds", resourceCulture); } } - + /// /// Looks up a localized string similar to An incorrect IAsyncResult was provided to an 'End' method. The IAsyncResult object passed to 'End' must be the one returned from the matching 'Begin' or passed to the callback provided to 'Begin'.. /// @@ -100,7 +110,7 @@ internal static string AsyncResult_ResultMismatch { return ResourceManager.GetString("AsyncResult_ResultMismatch", resourceCulture); } } - + /// /// Looks up a localized string similar to Found zero byte ranges. There must be at least one byte range provided.. /// @@ -109,7 +119,7 @@ internal static string ByteRangeStreamContentNoRanges { return ResourceManager.GetString("ByteRangeStreamContentNoRanges", resourceCulture); } } - + /// /// Looks up a localized string similar to The range unit '{0}' is not valid. The range must have a unit of '{1}'.. /// @@ -118,7 +128,7 @@ internal static string ByteRangeStreamContentNotBytesRange { return ResourceManager.GetString("ByteRangeStreamContentNotBytesRange", resourceCulture); } } - + /// /// Looks up a localized string similar to The stream over which '{0}' provides a range view must have a length greater than or equal to 1.. /// @@ -127,7 +137,7 @@ internal static string ByteRangeStreamEmpty { return ResourceManager.GetString("ByteRangeStreamEmpty", resourceCulture); } } - + /// /// Looks up a localized string similar to The 'From' value of the range must be less than or equal to {0}.. /// @@ -136,7 +146,16 @@ internal static string ByteRangeStreamInvalidFrom { return ResourceManager.GetString("ByteRangeStreamInvalidFrom", resourceCulture); } } - + + /// + /// Looks up a localized string similar to An attempt was made to move the position before the beginning of the stream.. + /// + internal static string ByteRangeStreamInvalidOffset { + get { + return ResourceManager.GetString("ByteRangeStreamInvalidOffset", resourceCulture); + } + } + /// /// Looks up a localized string similar to None of the requested ranges ({0}) overlap with the current extent of the selected resource.. /// @@ -145,7 +164,7 @@ internal static string ByteRangeStreamNoneOverlap { return ResourceManager.GetString("ByteRangeStreamNoneOverlap", resourceCulture); } } - + /// /// Looks up a localized string similar to The requested range ({0}) does not overlap with the current extent of the selected resource.. /// @@ -154,7 +173,7 @@ internal static string ByteRangeStreamNoOverlap { return ResourceManager.GetString("ByteRangeStreamNoOverlap", resourceCulture); } } - + /// /// Looks up a localized string similar to The stream over which '{0}' provides a range view must be seekable.. /// @@ -163,7 +182,7 @@ internal static string ByteRangeStreamNotSeekable { return ResourceManager.GetString("ByteRangeStreamNotSeekable", resourceCulture); } } - + /// /// Looks up a localized string similar to This is a read-only stream.. /// @@ -172,7 +191,7 @@ internal static string ByteRangeStreamReadOnly { return ResourceManager.GetString("ByteRangeStreamReadOnly", resourceCulture); } } - + /// /// Looks up a localized string similar to A null '{0}' is not valid.. /// @@ -181,7 +200,7 @@ internal static string CannotHaveNullInList { return ResourceManager.GetString("CannotHaveNullInList", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' of '{1}' cannot be used as a supported media type because it is a media range.. /// @@ -190,7 +209,7 @@ internal static string CannotUseMediaRangeForSupportedMediaType { return ResourceManager.GetString("CannotUseMediaRangeForSupportedMediaType", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' type cannot accept a null value for the value type '{1}'.. /// @@ -199,7 +218,7 @@ internal static string CannotUseNullValueType { return ResourceManager.GetString("CannotUseNullValueType", resourceCulture); } } - + /// /// Looks up a localized string similar to The specified value is not a valid cookie name.. /// @@ -208,7 +227,7 @@ internal static string CookieInvalidName { return ResourceManager.GetString("CookieInvalidName", resourceCulture); } } - + /// /// Looks up a localized string similar to Cookie cannot be null.. /// @@ -217,7 +236,7 @@ internal static string CookieNull { return ResourceManager.GetString("CookieNull", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' list is invalid because it contains one or more null items.. /// @@ -226,7 +245,7 @@ internal static string DelegatingHandlerArrayContainsNullItem { return ResourceManager.GetString("DelegatingHandlerArrayContainsNullItem", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' list is invalid because the property '{1}' of '{2}' is not null.. /// @@ -235,7 +254,7 @@ internal static string DelegatingHandlerArrayHasNonNullInnerHandler { return ResourceManager.GetString("DelegatingHandlerArrayHasNonNullInnerHandler", resourceCulture); } } - + /// /// Looks up a localized string similar to Error reading HTML form URL-encoded data stream.. /// @@ -244,7 +263,7 @@ internal static string ErrorReadingFormUrlEncodedStream { return ResourceManager.GetString("ErrorReadingFormUrlEncodedStream", resourceCulture); } } - + /// /// Looks up a localized string similar to Mismatched types at node '{0}'.. /// @@ -253,7 +272,7 @@ internal static string FormUrlEncodedMismatchingTypes { return ResourceManager.GetString("FormUrlEncodedMismatchingTypes", resourceCulture); } } - + /// /// Looks up a localized string similar to Error parsing HTML form URL-encoded data, byte {0}.. /// @@ -262,7 +281,7 @@ internal static string FormUrlEncodedParseError { return ResourceManager.GetString("FormUrlEncodedParseError", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid HTTP status code: '{0}'. The status code must be between {1} and {2}.. /// @@ -271,7 +290,7 @@ internal static string HttpInvalidStatusCode { return ResourceManager.GetString("HttpInvalidStatusCode", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid HTTP version: '{0}'. The version must start with the characters '{1}'.. /// @@ -280,7 +299,7 @@ internal static string HttpInvalidVersion { return ResourceManager.GetString("HttpInvalidVersion", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' of the '{1}' has already been read.. /// @@ -289,7 +308,7 @@ internal static string HttpMessageContentAlreadyRead { return ResourceManager.GetString("HttpMessageContentAlreadyRead", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' must be seekable in order to create an '{1}' instance containing an entity body. . /// @@ -298,7 +317,7 @@ internal static string HttpMessageContentStreamMustBeSeekable { return ResourceManager.GetString("HttpMessageContentStreamMustBeSeekable", resourceCulture); } } - + /// /// Looks up a localized string similar to Error reading HTTP message.. /// @@ -307,7 +326,7 @@ internal static string HttpMessageErrorReading { return ResourceManager.GetString("HttpMessageErrorReading", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid '{0}' instance provided. It does not have a content type header with a value of '{1}'.. /// @@ -316,7 +335,7 @@ internal static string HttpMessageInvalidMediaType { return ResourceManager.GetString("HttpMessageInvalidMediaType", resourceCulture); } } - + /// /// Looks up a localized string similar to HTTP Request URI cannot be an empty string.. /// @@ -325,7 +344,7 @@ internal static string HttpMessageParserEmptyUri { return ResourceManager.GetString("HttpMessageParserEmptyUri", resourceCulture); } } - + /// /// Looks up a localized string similar to Error parsing HTTP message header byte {0} of message {1}.. /// @@ -334,7 +353,7 @@ internal static string HttpMessageParserError { return ResourceManager.GetString("HttpMessageParserError", resourceCulture); } } - + /// /// Looks up a localized string similar to An invalid number of '{0}' header fields were present in the HTTP Request. It must contain exactly one '{0}' header field but found {1}.. /// @@ -343,7 +362,7 @@ internal static string HttpMessageParserInvalidHostCount { return ResourceManager.GetString("HttpMessageParserInvalidHostCount", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid URI scheme: '{0}'. The URI scheme must be a valid '{1}' scheme.. /// @@ -352,7 +371,7 @@ internal static string HttpMessageParserInvalidUriScheme { return ResourceManager.GetString("HttpMessageParserInvalidUriScheme", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid array at node '{0}'.. /// @@ -361,7 +380,7 @@ internal static string InvalidArrayInsert { return ResourceManager.GetString("InvalidArrayInsert", resourceCulture); } } - + /// /// Looks up a localized string similar to Traditional style array without '[]' is not supported with nested object at location {0}.. /// @@ -370,7 +389,16 @@ internal static string JQuery13CompatModeNotSupportNestedJson { return ResourceManager.GetString("JQuery13CompatModeNotSupportNestedJson", resourceCulture); } } - + + /// + /// Looks up a localized string similar to Unable to validate types on this platform when {0} is 'true'. Please reset {0} or move to a supported platform, one where the 'netstandard2.0' assembly is usable.. + /// + internal static string JsonMediaTypeFormatter_DCS_NotSupported { + get { + return ResourceManager.GetString("JsonMediaTypeFormatter_DCS_NotSupported", resourceCulture); + } + } + /// /// Looks up a localized string similar to The '{0}' method returned null. It must return a JSON serializer instance.. /// @@ -379,7 +407,7 @@ internal static string JsonSerializerFactoryReturnedNull { return ResourceManager.GetString("JsonSerializerFactoryReturnedNull", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' method threw an exception when attempting to create a JSON serializer.. /// @@ -388,7 +416,7 @@ internal static string JsonSerializerFactoryThrew { return ResourceManager.GetString("JsonSerializerFactoryThrew", resourceCulture); } } - + /// /// Looks up a localized string similar to The maximum read depth ({0}) has been exceeded because the form url-encoded data being read has more levels of nesting than is allowed.. /// @@ -397,7 +425,7 @@ internal static string MaxDepthExceeded { return ResourceManager.GetString("MaxDepthExceeded", resourceCulture); } } - + /// /// Looks up a localized string similar to The number of keys in a NameValueCollection has exceeded the limit of '{0}'. You can adjust it by modifying the MaxHttpCollectionKeys property on the '{1}' class.. /// @@ -406,7 +434,7 @@ internal static string MaxHttpCollectionKeyLimitReached { return ResourceManager.GetString("MaxHttpCollectionKeyLimitReached", resourceCulture); } } - + /// /// Looks up a localized string similar to Error parsing BSON data; unable to read content as a {0}.. /// @@ -415,7 +443,7 @@ internal static string MediaTypeFormatter_BsonParseError_MissingData { return ResourceManager.GetString("MediaTypeFormatter_BsonParseError_MissingData", resourceCulture); } } - + /// /// Looks up a localized string similar to Error parsing BSON data; unexpected dictionary content: {0} entries, first key '{1}'.. /// @@ -424,7 +452,7 @@ internal static string MediaTypeFormatter_BsonParseError_UnexpectedData { return ResourceManager.GetString("MediaTypeFormatter_BsonParseError_UnexpectedData", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' method returned null. It must return a JSON reader instance.. /// @@ -433,7 +461,7 @@ internal static string MediaTypeFormatter_JsonReaderFactoryReturnedNull { return ResourceManager.GetString("MediaTypeFormatter_JsonReaderFactoryReturnedNull", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' method returned null. It must return a JSON writer instance.. /// @@ -442,7 +470,7 @@ internal static string MediaTypeFormatter_JsonWriterFactoryReturnedNull { return ResourceManager.GetString("MediaTypeFormatter_JsonWriterFactoryReturnedNull", resourceCulture); } } - + /// /// Looks up a localized string similar to The media type formatter of type '{0}' does not support reading because it does not implement the ReadFromStreamAsync method.. /// @@ -451,7 +479,7 @@ internal static string MediaTypeFormatterCannotRead { return ResourceManager.GetString("MediaTypeFormatterCannotRead", resourceCulture); } } - + /// /// Looks up a localized string similar to The media type formatter of type '{0}' does not support reading because it does not implement the ReadFromStream method.. /// @@ -460,7 +488,7 @@ internal static string MediaTypeFormatterCannotReadSync { return ResourceManager.GetString("MediaTypeFormatterCannotReadSync", resourceCulture); } } - + /// /// Looks up a localized string similar to The media type formatter of type '{0}' does not support writing because it does not implement the WriteToStreamAsync method.. /// @@ -469,7 +497,7 @@ internal static string MediaTypeFormatterCannotWrite { return ResourceManager.GetString("MediaTypeFormatterCannotWrite", resourceCulture); } } - + /// /// Looks up a localized string similar to The media type formatter of type '{0}' does not support writing because it does not implement the WriteToStream method.. /// @@ -478,7 +506,7 @@ internal static string MediaTypeFormatterCannotWriteSync { return ResourceManager.GetString("MediaTypeFormatterCannotWriteSync", resourceCulture); } } - + /// /// Looks up a localized string similar to No encoding found for media type formatter '{0}'. There must be at least one supported encoding registered in order for the media type formatter to read or write content.. /// @@ -487,7 +515,7 @@ internal static string MediaTypeFormatterNoEncoding { return ResourceManager.GetString("MediaTypeFormatterNoEncoding", resourceCulture); } } - + /// /// Looks up a localized string similar to MIME multipart boundary cannot end with an empty space.. /// @@ -496,7 +524,7 @@ internal static string MimeMultipartParserBadBoundary { return ResourceManager.GetString("MimeMultipartParserBadBoundary", resourceCulture); } } - + /// /// Looks up a localized string similar to Did not find required '{0}' header field in MIME multipart body part.. /// @@ -505,7 +533,7 @@ internal static string MultipartFormDataStreamProviderNoContentDisposition { return ResourceManager.GetString("MultipartFormDataStreamProviderNoContentDisposition", resourceCulture); } } - + /// /// Looks up a localized string similar to Could not determine a valid local file name for the multipart body part.. /// @@ -514,7 +542,7 @@ internal static string MultipartStreamProviderInvalidLocalFileName { return ResourceManager.GetString("MultipartStreamProviderInvalidLocalFileName", resourceCulture); } } - + /// /// Looks up a localized string similar to Nested bracket is not valid for '{0}' data at position {1}.. /// @@ -523,7 +551,7 @@ internal static string NestedBracketNotValid { return ResourceManager.GetString("NestedBracketNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to A non-null request URI must be provided to determine if a '{0}' matches a given request or response message.. /// @@ -532,7 +560,7 @@ internal static string NonNullUriRequiredForMediaTypeMapping { return ResourceManager.GetString("NonNullUriRequiredForMediaTypeMapping", resourceCulture); } } - + /// /// Looks up a localized string similar to No MediaTypeFormatter is available to read an object of type '{0}' from content with media type '{1}'.. /// @@ -541,7 +569,34 @@ internal static string NoReadSerializerAvailable { return ResourceManager.GetString("NoReadSerializerAvailable", resourceCulture); } } - + + /// + /// Looks up a localized string similar to Stream does not support reading.. + /// + internal static string NotSupported_UnreadableStream { + get { + return ResourceManager.GetString("NotSupported_UnreadableStream", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stream does not support seeking.. + /// + internal static string NotSupported_UnseekableStream { + get { + return ResourceManager.GetString("NotSupported_UnseekableStream", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stream does not support writing.. + /// + internal static string NotSupported_UnwritableStream { + get { + return ResourceManager.GetString("NotSupported_UnwritableStream", resourceCulture); + } + } + /// /// Looks up a localized string similar to An object of type '{0}' cannot be used with a type parameter of '{1}'.. /// @@ -550,7 +605,7 @@ internal static string ObjectAndTypeDisagree { return ResourceManager.GetString("ObjectAndTypeDisagree", resourceCulture); } } - + /// /// Looks up a localized string similar to The configured formatter '{0}' cannot write an object of type '{1}'.. /// @@ -559,7 +614,16 @@ internal static string ObjectContent_FormatterCannotWriteType { return ResourceManager.GetString("ObjectContent_FormatterCannotWriteType", resourceCulture); } } - + + /// + /// Looks up a localized string similar to Cannot access a closed stream.. + /// + internal static string ObjectDisposed_StreamClosed { + get { + return ResourceManager.GetString("ObjectDisposed_StreamClosed", resourceCulture); + } + } + /// /// Looks up a localized string similar to Query string name cannot be null.. /// @@ -568,7 +632,7 @@ internal static string QueryStringNameShouldNotNull { return ResourceManager.GetString("QueryStringNameShouldNotNull", resourceCulture); } } - + /// /// Looks up a localized string similar to Unexpected end of HTTP message stream. HTTP message is not complete.. /// @@ -577,7 +641,7 @@ internal static string ReadAsHttpMessageUnexpectedTermination { return ResourceManager.GetString("ReadAsHttpMessageUnexpectedTermination", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid '{0}' instance provided. It does not have a '{1}' content-type header with a '{2}' parameter.. /// @@ -586,7 +650,7 @@ internal static string ReadAsMimeMultipartArgumentNoBoundary { return ResourceManager.GetString("ReadAsMimeMultipartArgumentNoBoundary", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid '{0}' instance provided. It does not have a content-type header value. '{0}' instances must have a content-type header starting with '{1}'.. /// @@ -595,7 +659,7 @@ internal static string ReadAsMimeMultipartArgumentNoContentType { return ResourceManager.GetString("ReadAsMimeMultipartArgumentNoContentType", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid '{0}' instance provided. It does not have a content type header starting with '{1}'.. /// @@ -604,7 +668,7 @@ internal static string ReadAsMimeMultipartArgumentNoMultipart { return ResourceManager.GetString("ReadAsMimeMultipartArgumentNoMultipart", resourceCulture); } } - + /// /// Looks up a localized string similar to Error reading MIME multipart body part.. /// @@ -613,7 +677,7 @@ internal static string ReadAsMimeMultipartErrorReading { return ResourceManager.GetString("ReadAsMimeMultipartErrorReading", resourceCulture); } } - + /// /// Looks up a localized string similar to Error writing MIME multipart body part to output stream.. /// @@ -622,7 +686,7 @@ internal static string ReadAsMimeMultipartErrorWriting { return ResourceManager.GetString("ReadAsMimeMultipartErrorWriting", resourceCulture); } } - + /// /// Looks up a localized string similar to Error parsing MIME multipart body part header byte {0} of data segment {1}.. /// @@ -631,7 +695,7 @@ internal static string ReadAsMimeMultipartHeaderParseError { return ResourceManager.GetString("ReadAsMimeMultipartHeaderParseError", resourceCulture); } } - + /// /// Looks up a localized string similar to Error parsing MIME multipart message byte {0} of data segment {1}.. /// @@ -640,7 +704,7 @@ internal static string ReadAsMimeMultipartParseError { return ResourceManager.GetString("ReadAsMimeMultipartParseError", resourceCulture); } } - + /// /// Looks up a localized string similar to The stream provider of type '{0}' threw an exception.. /// @@ -649,7 +713,7 @@ internal static string ReadAsMimeMultipartStreamProviderException { return ResourceManager.GetString("ReadAsMimeMultipartStreamProviderException", resourceCulture); } } - + /// /// Looks up a localized string similar to The stream provider of type '{0}' returned null. It must return a writable '{1}' instance.. /// @@ -658,7 +722,7 @@ internal static string ReadAsMimeMultipartStreamProviderNull { return ResourceManager.GetString("ReadAsMimeMultipartStreamProviderNull", resourceCulture); } } - + /// /// Looks up a localized string similar to The stream provider of type '{0}' returned a read-only stream. It must return a writable '{1}' instance.. /// @@ -667,7 +731,7 @@ internal static string ReadAsMimeMultipartStreamProviderReadOnly { return ResourceManager.GetString("ReadAsMimeMultipartStreamProviderReadOnly", resourceCulture); } } - + /// /// Looks up a localized string similar to Unexpected end of MIME multipart stream. MIME multipart message is not complete.. /// @@ -676,7 +740,7 @@ internal static string ReadAsMimeMultipartUnexpectedTermination { return ResourceManager.GetString("ReadAsMimeMultipartUnexpectedTermination", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' method in '{1}' returned null. It must return a RemoteStreamResult instance containing a writable stream and a valid URL.. /// @@ -685,7 +749,7 @@ internal static string RemoteStreamInfoCannotBeNull { return ResourceManager.GetString("RemoteStreamInfoCannotBeNull", resourceCulture); } } - + /// /// Looks up a localized string similar to The '{0}' serializer cannot serialize the type '{1}'.. /// @@ -694,7 +758,7 @@ internal static string SerializerCannotSerializeType { return ResourceManager.GetString("SerializerCannotSerializeType", resourceCulture); } } - + /// /// Looks up a localized string similar to There is an unmatched opened bracket for the '{0}' at position {1}.. /// @@ -703,7 +767,7 @@ internal static string UnMatchedBracketNotValid { return ResourceManager.GetString("UnMatchedBracketNotValid", resourceCulture); } } - + /// /// Looks up a localized string similar to Indentation is not supported by '{0}'.. /// @@ -712,7 +776,16 @@ internal static string UnsupportedIndent { return ResourceManager.GetString("UnsupportedIndent", resourceCulture); } } - + + /// + /// Looks up a localized string similar to Unable to validate types on this platform when {0} is 'false'. Please set {0} or move to a supported platform, one where the 'netstandard2.0' assembly is usable.. + /// + internal static string XmlMediaTypeFormatter_DCS_NotSupported { + get { + return ResourceManager.GetString("XmlMediaTypeFormatter_DCS_NotSupported", resourceCulture); + } + } + /// /// Looks up a localized string similar to The object of type '{0}' returned by {1} must be an instance of either XmlObjectSerializer or XmlSerializer.. /// @@ -721,7 +794,7 @@ internal static string XmlMediaTypeFormatter_InvalidSerializerType { return ResourceManager.GetString("XmlMediaTypeFormatter_InvalidSerializerType", resourceCulture); } } - + /// /// Looks up a localized string similar to The object returned by {0} must not be a null value.. /// diff --git a/src/System.Net.Http.Formatting/Properties/Resources.resx b/src/System.Net.Http.Formatting/Properties/Resources.resx index 77b63a96a..82d90e68c 100644 --- a/src/System.Net.Http.Formatting/Properties/Resources.resx +++ b/src/System.Net.Http.Formatting/Properties/Resources.resx @@ -1,17 +1,17 @@  - @@ -339,4 +339,28 @@ The '{0}' method in '{1}' returned null. It must return a RemoteStreamResult instance containing a writable stream and a valid URL. + + An attempt was made to move the position before the beginning of the stream. + + + Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. + + + Stream does not support reading. + + + Stream does not support seeking. + + + Stream does not support writing. + + + Cannot access a closed stream. + + + Unable to validate types on this platform when {0} is 'true'. Please reset {0} or move to a supported platform, one where the .NET Standard 2.0 assembly is usable. + + + Unable to validate types on this platform when {0} is 'false'. Please set {0} or move to a supported platform, one where the .NET Standard 2.0 assembly is usable. + \ No newline at end of file diff --git a/src/System.Net.Http.Formatting/PushStreamContent.cs b/src/System.Net.Http.Formatting/PushStreamContent.cs index a8df4f262..8b4a72b3c 100644 --- a/src/System.Net.Http.Formatting/PushStreamContent.cs +++ b/src/System.Net.Http.Formatting/PushStreamContent.cs @@ -14,7 +14,7 @@ namespace System.Net.Http { /// /// Provides an implementation that exposes an output - /// which can be written to directly. The ability to push data to the output stream differs from the + /// which can be written to directly. The ability to push data to the output stream differs from the /// where data is pulled and not pushed. /// public class PushStreamContent : HttpContent @@ -24,8 +24,8 @@ public class PushStreamContent : HttpContent /// /// Initializes a new instance of the class. The /// action is called when an output stream - /// has become available allowing the action to write to it directly. When the - /// stream is closed, it will signal to the content that is has completed and the + /// has become available allowing the action to write to it directly. When the + /// stream is closed, it will signal to the content that it has completed and the /// HTTP request or response will be completed. /// /// The action to call when an output stream is available. @@ -35,10 +35,11 @@ public PushStreamContent(Action onStreamA } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The action to call when an output stream is available. The stream is automatically - /// closed when the return task is completed. + /// The action to call when an output stream is available. When the + /// output stream is closed or disposed, it will signal to the content that it has completed and the + /// HTTP request or response will be completed. public PushStreamContent(Func onStreamAvailable) : this(onStreamAvailable, (MediaTypeHeaderValue)null) { @@ -47,6 +48,8 @@ public PushStreamContent(Func onStr /// /// Initializes a new instance of the class with the given media type. /// + /// The action to call when an output stream is available. + /// The value of the Content-Type content header on an HTTP response. public PushStreamContent(Action onStreamAvailable, string mediaType) : this(Taskify(onStreamAvailable), new MediaTypeHeaderValue(mediaType)) { @@ -55,6 +58,10 @@ public PushStreamContent(Action onStreamA /// /// Initializes a new instance of the class with the given media type. /// + /// The action to call when an output stream is available. When the + /// output stream is closed or disposed, it will signal to the content that it has completed and the + /// HTTP request or response will be completed. + /// The value of the Content-Type content header on an HTTP response. public PushStreamContent(Func onStreamAvailable, string mediaType) : this(onStreamAvailable, new MediaTypeHeaderValue(mediaType)) { @@ -63,6 +70,8 @@ public PushStreamContent(Func onStr /// /// Initializes a new instance of the class with the given . /// + /// The action to call when an output stream is available. + /// The value of the Content-Type content header on an HTTP response. public PushStreamContent(Action onStreamAvailable, MediaTypeHeaderValue mediaType) : this(Taskify(onStreamAvailable), mediaType) { @@ -71,6 +80,10 @@ public PushStreamContent(Action onStreamA /// /// Initializes a new instance of the class with the given . /// + /// The action to call when an output stream is available. When the + /// output stream is closed or disposed, it will signal to the content that it has completed and the + /// HTTP request or response will be completed. + /// The value of the Content-Type content header on an HTTP response. public PushStreamContent(Func onStreamAvailable, MediaTypeHeaderValue mediaType) { if (onStreamAvailable == null) @@ -98,8 +111,8 @@ private static Func Taskify( } /// - /// When this method is called, it calls the action provided in the constructor with the output - /// stream to write to. Once the action has completed its work it closes the stream which will + /// When this method is called, it calls the action provided in the constructor with the output + /// stream to write to. Once the action has completed its work it closes the stream which will /// close this content instance and complete the HTTP request or response. /// /// The to which to write. @@ -140,10 +153,10 @@ public CompleteTaskOnCloseStream(Stream innerStream, TaskCompletionSource _serializeToStreamTask = serializeToStreamTask; } -#if NETFX_CORE +#if NETSTANDARD1_3 [SuppressMessage( - "Microsoft.Usage", - "CA2215:Dispose methods should call base class dispose", + "Microsoft.Usage", + "CA2215:Dispose methods should call base class dispose", Justification = "See comments, this is intentional.")] protected override void Dispose(bool disposing) { diff --git a/src/System.Net.Http.Formatting/Settings.StyleCop b/src/System.Net.Http.Formatting/Settings.StyleCop deleted file mode 100644 index 5b387864d..000000000 --- a/src/System.Net.Http.Formatting/Settings.StyleCop +++ /dev/null @@ -1,10 +0,0 @@ - - - UriQueryUtility.cs - - - False - - - - \ No newline at end of file diff --git a/src/System.Net.Http.Formatting/System.Net.Http.Formatting.csproj b/src/System.Net.Http.Formatting/System.Net.Http.Formatting.csproj index 42c7a509f..bf2cf46b1 100644 --- a/src/System.Net.Http.Formatting/System.Net.Http.Formatting.csproj +++ b/src/System.Net.Http.Formatting/System.Net.Http.Formatting.csproj @@ -10,171 +10,88 @@ $(OutputPath)$(AssemblyName).xml $(CodeAnalysis) ..\Strict.ruleset - $(DefineConstants);ASPNETMVC + $(DefineConstants);ASPNETHTTPFORMATTING Client 1591 + - + + + ..\..\packages\System.Buffers.4.5.1\lib\netstandard2.0\System.Buffers.dll False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + False - + + ..\..\packages\System.Memory.4.5.5\lib\netstandard2.0\System.Memory.dll + False + False + + + ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + False + False + - - - - Properties\CommonAssemblyInfo.cs - - - Common\CollectionExtensions.cs - - - Common\Error.cs - - - Common\ListWrapperCollection.cs - - - Common\TaskHelpers.cs - - - Common\TaskHelpersExtensions.cs - - - Common\UriQueryUtility.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + ..\..\packages\NETStandard.Library.2.0.3\lib\netstandard2.0\netstandard.dll + False + False + + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + False + False + + + ..\..\packages\Newtonsoft.Json.Bson.1.0.2\lib\net45\Newtonsoft.Json.Bson.dll + False + False + + + + + + + + + + + - Properties\CommonWebApiResources.Designer.cs True - True CommonWebApiResources.resx + True + Properties\CommonWebApiResources.Designer.cs - - - Properties\CommonWebApiResources.resx ResXFileCodeGenerator CommonWebApiResources.Designer.cs + Properties\CommonWebApiResources.resx - - + + + True + Resources.resx + True + ResXFileCodeGenerator Resources.Designer.cs Designer - - - - CodeAnalysisDictionary.xml - - - + + + + - \ No newline at end of file + diff --git a/src/System.Net.Http.Formatting/UriExtensions.cs b/src/System.Net.Http.Formatting/UriExtensions.cs index ab83ec938..cf531431a 100644 --- a/src/System.Net.Http.Formatting/UriExtensions.cs +++ b/src/System.Net.Http.Formatting/UriExtensions.cs @@ -18,21 +18,12 @@ namespace System.Net.Http [EditorBrowsable(EditorBrowsableState.Never)] public static class UriExtensions { -#if NETFX_CORE - /// - /// Parses the query portion of the specified . - /// - /// The instance from which to read. - /// A containing the parsed result. - public static HttpValueCollection ParseQueryString(this Uri address) -#else /// /// Parses the query portion of the specified . /// /// The instance from which to read. /// A containing the parsed result. public static NameValueCollection ParseQueryString(this Uri address) -#endif { if (address == null) { diff --git a/src/System.Net.Http.Formatting/packages.config b/src/System.Net.Http.Formatting/packages.config index 992a6e6d0..1ff2795f6 100644 --- a/src/System.Net.Http.Formatting/packages.config +++ b/src/System.Net.Http.Formatting/packages.config @@ -1,4 +1,9 @@  - + + + + + + \ No newline at end of file diff --git a/src/System.Web.Http.Cors/CorsHttpConfigurationExtensions.cs b/src/System.Web.Http.Cors/CorsHttpConfigurationExtensions.cs index 3bf6631b5..42190f97b 100644 --- a/src/System.Web.Http.Cors/CorsHttpConfigurationExtensions.cs +++ b/src/System.Web.Http.Cors/CorsHttpConfigurationExtensions.cs @@ -26,7 +26,17 @@ public static class CorsHttpConfigurationExtensions /// The . public static void EnableCors(this HttpConfiguration httpConfiguration) { - EnableCors(httpConfiguration, null); + EnableCors(httpConfiguration, null, false); + } + + /// + /// Enables the support for CORS. + /// + /// The . + /// Indicates whether upstream exceptions should be rethrown + public static void EnableCors(this HttpConfiguration httpConfiguration, bool rethrowExceptions) + { + EnableCors(httpConfiguration, null, rethrowExceptions); } /// @@ -34,8 +44,20 @@ public static void EnableCors(this HttpConfiguration httpConfiguration) /// /// The . /// The default . - /// httpConfiguration public static void EnableCors(this HttpConfiguration httpConfiguration, ICorsPolicyProvider defaultPolicyProvider) + { + EnableCors(httpConfiguration, defaultPolicyProvider, false); + } + + /// + /// Enables the support for CORS. + /// + /// The . + /// The default . + /// Indicates whether upstream exceptions should be rethrown + /// httpConfiguration + public static void EnableCors(this HttpConfiguration httpConfiguration, ICorsPolicyProvider defaultPolicyProvider, + bool rethrowExceptions) { if (httpConfiguration == null) { @@ -49,11 +71,11 @@ public static void EnableCors(this HttpConfiguration httpConfiguration, ICorsPol httpConfiguration.SetCorsPolicyProviderFactory(policyProviderFactory); } - AddCorsMessageHandler(httpConfiguration); + AddCorsMessageHandler(httpConfiguration, rethrowExceptions); } [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Caller owns the disposable object")] - private static void AddCorsMessageHandler(this HttpConfiguration httpConfiguration) + private static void AddCorsMessageHandler(this HttpConfiguration httpConfiguration, bool rethrowExceptions) { object corsEnabled; if (!httpConfiguration.Properties.TryGetValue(CorsEnabledKey, out corsEnabled)) @@ -64,7 +86,7 @@ private static void AddCorsMessageHandler(this HttpConfiguration httpConfigurati if (!config.Properties.TryGetValue(CorsEnabledKey, out corsEnabled)) { // Execute this in the Initializer to ensure that the CorsMessageHandler is added last. - config.MessageHandlers.Add(new CorsMessageHandler(config)); + config.MessageHandlers.Add(new CorsMessageHandler(config, rethrowExceptions)); ITraceWriter traceWriter = config.Services.GetTraceWriter(); diff --git a/src/System.Web.Http.Cors/CorsMessageHandler.cs b/src/System.Web.Http.Cors/CorsMessageHandler.cs index 5d683ca26..5308ee340 100644 --- a/src/System.Web.Http.Cors/CorsMessageHandler.cs +++ b/src/System.Web.Http.Cors/CorsMessageHandler.cs @@ -18,13 +18,24 @@ namespace System.Web.Http.Cors public class CorsMessageHandler : DelegatingHandler { private HttpConfiguration _httpConfiguration; + private bool _rethrowExceptions; /// /// Initializes a new instance of the class. /// /// The . /// httpConfiguration - public CorsMessageHandler(HttpConfiguration httpConfiguration) + public CorsMessageHandler(HttpConfiguration httpConfiguration) : this(httpConfiguration, false) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The . + /// Indicates whether upstream exceptions should be rethrown + /// httpConfiguration + public CorsMessageHandler(HttpConfiguration httpConfiguration, bool rethrowExceptions) { if (httpConfiguration == null) { @@ -32,6 +43,7 @@ public CorsMessageHandler(HttpConfiguration httpConfiguration) } _httpConfiguration = httpConfiguration; + _rethrowExceptions = rethrowExceptions; } /// @@ -60,6 +72,11 @@ protected async override Task SendAsync(HttpRequestMessage } catch (Exception exception) { + if (_rethrowExceptions) + { + throw; + } + return HandleException(request, exception); } } diff --git a/src/System.Web.Http.Owin/HttpMessageHandlerAdapter.cs b/src/System.Web.Http.Owin/HttpMessageHandlerAdapter.cs index b8c6fc648..ac118a754 100644 --- a/src/System.Web.Http.Owin/HttpMessageHandlerAdapter.cs +++ b/src/System.Web.Http.Owin/HttpMessageHandlerAdapter.cs @@ -275,7 +275,7 @@ private static async Task CreateBufferedRequestContentAsync(IOwinRe } else { - buffer = new MemoryStream(contentLength.Value); + buffer = new MemoryStream(Math.Min(4 * 1024, contentLength.Value)); } cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/System.Web.Http.Owin/OwinHttpRequestContext.cs b/src/System.Web.Http.Owin/OwinHttpRequestContext.cs index a2321a2ec..d76c8a19c 100644 --- a/src/System.Web.Http.Owin/OwinHttpRequestContext.cs +++ b/src/System.Web.Http.Owin/OwinHttpRequestContext.cs @@ -182,7 +182,7 @@ public override string VirtualPathRoot { // Set the virtual path root for link resolution and link generation to work // OWIN spec requires request path base to be either the empty string or start with "/" - string requestPathBase = _context.Request.PathBase.ToString(); + string requestPathBase = _context.Request.PathBase.Value; _virtualPathRoot = String.IsNullOrEmpty(requestPathBase) ? "/" : requestPathBase; _virtualPathRootSet = true; } diff --git a/src/System.Web.Http.Owin/PassiveAuthenticationMessageHandler.cs b/src/System.Web.Http.Owin/PassiveAuthenticationMessageHandler.cs index c1587e537..daf526bd4 100644 --- a/src/System.Web.Http.Owin/PassiveAuthenticationMessageHandler.cs +++ b/src/System.Web.Http.Owin/PassiveAuthenticationMessageHandler.cs @@ -9,9 +9,7 @@ using System.Threading.Tasks; using System.Web.Http.Controllers; using System.Web.Http.Filters; -using System.Web.Http.Hosting; using System.Web.Http.Owin.Properties; -using Microsoft.Owin; using Microsoft.Owin.Security; namespace System.Web.Http.Owin @@ -37,27 +35,36 @@ protected override async Task SendAsync(HttpRequestMessage throw new ArgumentNullException("request"); } - SetCurrentPrincipalToAnonymous(request); - - HttpResponseMessage response = await base.SendAsync(request, cancellationToken); + HttpResponseMessage response; + var previousPrincipal = SetCurrentPrincipal(request, _anonymousPrincipal.Value); + try + { + response = await base.SendAsync(request, cancellationToken); + } + finally + { + SetCurrentPrincipal(request, previousPrincipal); + } SuppressDefaultAuthenticationChallenges(request); return response; } - private static void SetCurrentPrincipalToAnonymous(HttpRequestMessage request) + private static IPrincipal SetCurrentPrincipal(HttpRequestMessage request, IPrincipal principal) { Contract.Assert(request != null); HttpRequestContext requestContext = request.GetRequestContext(); - if (requestContext == null) { throw new ArgumentException(OwinResources.Request_RequestContextMustNotBeNull, "request"); } - requestContext.Principal = _anonymousPrincipal.Value; + var previousPrincipal = requestContext.Principal; + requestContext.Principal = principal; + + return previousPrincipal; } private static void SuppressDefaultAuthenticationChallenges(HttpRequestMessage request) diff --git a/src/System.Web.Http.Owin/System.Web.Http.Owin.csproj b/src/System.Web.Http.Owin/System.Web.Http.Owin.csproj index 40565650e..ae8d5176d 100644 --- a/src/System.Web.Http.Owin/System.Web.Http.Owin.csproj +++ b/src/System.Web.Http.Owin/System.Web.Http.Owin.csproj @@ -14,7 +14,7 @@ - ..\..\packages\Microsoft.Owin.2.0.2\lib\net45\Microsoft.Owin.dll + ..\..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll ..\..\packages\Owin.1.0\lib\net40\Owin.dll diff --git a/src/System.Web.Http.Owin/packages.config b/src/System.Web.Http.Owin/packages.config index 57b34eaa5..a288e84ae 100644 --- a/src/System.Web.Http.Owin/packages.config +++ b/src/System.Web.Http.Owin/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/System.Web.Http.SignalR/System.Web.Http.SignalR.csproj b/src/System.Web.Http.SignalR/System.Web.Http.SignalR.csproj index 8a1146a62..e8aeaff50 100644 --- a/src/System.Web.Http.SignalR/System.Web.Http.SignalR.csproj +++ b/src/System.Web.Http.SignalR/System.Web.Http.SignalR.csproj @@ -16,9 +16,10 @@ ..\..\packages\Microsoft.AspNet.SignalR.Core.1.0.0\lib\net40\Microsoft.AspNet.SignalR.Core.dll - + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + False diff --git a/src/System.Web.Http.SignalR/packages.config b/src/System.Web.Http.SignalR/packages.config index 6342f7fc0..253454ad2 100644 --- a/src/System.Web.Http.SignalR/packages.config +++ b/src/System.Web.Http.SignalR/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/System.Web.Http.Tracing/System.Web.Http.Tracing.csproj b/src/System.Web.Http.Tracing/System.Web.Http.Tracing.csproj index 7dcda357c..139282520 100644 --- a/src/System.Web.Http.Tracing/System.Web.Http.Tracing.csproj +++ b/src/System.Web.Http.Tracing/System.Web.Http.Tracing.csproj @@ -13,9 +13,10 @@ $(DefineConstants);ASPNETMVC - + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + False diff --git a/src/System.Web.Http.Tracing/packages.config b/src/System.Web.Http.Tracing/packages.config index 992a6e6d0..093dcd239 100644 --- a/src/System.Web.Http.Tracing/packages.config +++ b/src/System.Web.Http.Tracing/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/System.Web.Http.WebHost/HttpControllerHandler.cs b/src/System.Web.Http.WebHost/HttpControllerHandler.cs index 9a78f57f3..213f0e982 100644 --- a/src/System.Web.Http.WebHost/HttpControllerHandler.cs +++ b/src/System.Web.Http.WebHost/HttpControllerHandler.cs @@ -717,14 +717,17 @@ public Task WriteToStreamAsync(Stream stream, TransportContext context) return SerializeToStreamAsync(stream, context); } - public bool TryCalculateLength(out long length) + public Task GetContentReadStreamAsync() { - return TryComputeLength(out length); + return CreateContentReadStreamAsync(); } - public Task GetContentReadStreamAsync() + protected override bool TryComputeLength(out long length) { - return CreateContentReadStreamAsync(); + // Do not attempt to calculate length because SeekableBufferedRequestStream (for example) + // may report 0 until the underlying Stream has been read to end. + length = 0L; + return false; } } @@ -762,7 +765,10 @@ protected override Task CreateContentReadStreamAsync() protected override bool TryComputeLength(out long length) { - return StreamContent.TryCalculateLength(out length); + // Do not attempt to calculate length because SeekableBufferedRequestStream (for example) + // may report 0 until the underlying Stream has been read to end. + length = 0L; + return false; } } } diff --git a/src/System.Web.Http/Batch/DefaultHttpBatchHandler.cs b/src/System.Web.Http/Batch/DefaultHttpBatchHandler.cs index ca5412816..62171a318 100644 --- a/src/System.Web.Http/Batch/DefaultHttpBatchHandler.cs +++ b/src/System.Web.Http/Batch/DefaultHttpBatchHandler.cs @@ -187,7 +187,7 @@ public virtual async Task> ParseBatchRequestsAsync(Htt foreach (HttpContent httpContent in streamProvider.Contents) { cancellationToken.ThrowIfCancellationRequested(); - HttpRequestMessage innerRequest = await httpContent.ReadAsHttpRequestMessageAsync(); + HttpRequestMessage innerRequest = request.RequestUri == null ? await httpContent.ReadAsHttpRequestMessageAsync() : await httpContent.ReadAsHttpRequestMessageAsync(request.RequestUri.Scheme); innerRequest.CopyBatchRequestProperties(request); requests.Add(innerRequest); } diff --git a/src/System.Web.Http/Controllers/ReflectedHttpActionDescriptor.cs b/src/System.Web.Http/Controllers/ReflectedHttpActionDescriptor.cs index d663000b6..f1714ff77 100644 --- a/src/System.Web.Http/Controllers/ReflectedHttpActionDescriptor.cs +++ b/src/System.Web.Http/Controllers/ReflectedHttpActionDescriptor.cs @@ -400,7 +400,7 @@ private static Func> GetExecutor(MethodInfo metho // Call method UnaryExpression instanceCast = (!methodInfo.IsStatic) ? Expression.Convert(instanceParameter, methodInfo.ReflectedType) : null; - MethodCallExpression methodCall = methodCall = Expression.Call(instanceCast, methodInfo, parameters); + MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameters); // methodCall is "((MethodInstanceType) instance).method((T0) parameters[0], (T1) parameters[1], ...)" // Create function diff --git a/src/System.Web.Http/Description/ApiDescription.cs b/src/System.Web.Http/Description/ApiDescription.cs index b6f069b54..2e323fc14 100644 --- a/src/System.Web.Http/Description/ApiDescription.cs +++ b/src/System.Web.Http/Description/ApiDescription.cs @@ -22,6 +22,7 @@ public ApiDescription() SupportedRequestBodyFormatters = new Collection(); SupportedResponseFormatters = new Collection(); ParameterDescriptions = new Collection(); + ResponseDescription = new ResponseDescription(); } /// diff --git a/src/System.Web.Http/Hosting/SuppressHostPrincipalMessageHandler.cs b/src/System.Web.Http/Hosting/SuppressHostPrincipalMessageHandler.cs index 17c1b83c8..dc5084f59 100644 --- a/src/System.Web.Http/Hosting/SuppressHostPrincipalMessageHandler.cs +++ b/src/System.Web.Http/Hosting/SuppressHostPrincipalMessageHandler.cs @@ -25,7 +25,7 @@ public class SuppressHostPrincipalMessageHandler : DelegatingHandler () => new ClaimsPrincipal(new ClaimsIdentity()), isThreadSafe: true); /// - protected override Task SendAsync(HttpRequestMessage request, + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) @@ -33,23 +33,31 @@ protected override Task SendAsync(HttpRequestMessage reques throw new ArgumentNullException("request"); } - SetCurrentPrincipalToAnonymous(request); - - return base.SendAsync(request, cancellationToken); + var previousPrincipal = SetCurrentPrincipal(request, _anonymousPrincipal.Value); + try + { + return await base.SendAsync(request, cancellationToken); + } + finally + { + SetCurrentPrincipal(request, previousPrincipal); + } } - private static void SetCurrentPrincipalToAnonymous(HttpRequestMessage request) + private static IPrincipal SetCurrentPrincipal(HttpRequestMessage request, IPrincipal principal) { Contract.Assert(request != null); HttpRequestContext requestContext = request.GetRequestContext(); - if (requestContext == null) { throw new ArgumentException(SRResources.Request_RequestContextMustNotBeNull, "request"); } - requestContext.Principal = _anonymousPrincipal.Value; + var previousPrincipal = requestContext.Principal; + requestContext.Principal = principal; + + return previousPrincipal; } } } diff --git a/src/System.Web.Http/ModelBinding/ErrorParameterBinding.cs b/src/System.Web.Http/ModelBinding/ErrorParameterBinding.cs index 05334819d..57b9c0b77 100644 --- a/src/System.Web.Http/ModelBinding/ErrorParameterBinding.cs +++ b/src/System.Web.Http/ModelBinding/ErrorParameterBinding.cs @@ -20,7 +20,7 @@ public ErrorParameterBinding(HttpParameterDescriptor descriptor, string message) { if (message == null) { - throw Error.ArgumentNull(message); + throw Error.ArgumentNull("message"); } _message = message; } @@ -36,7 +36,7 @@ public override string ErrorMessage public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) { // Caller should have already checked IsError before executing, so we shoulnd't be here. - return TaskHelpers.FromError(new InvalidOperationException()); + return TaskHelpers.FromError(new InvalidOperationException()); } } } diff --git a/src/System.Web.Http/Results/OkResult.cs b/src/System.Web.Http/Results/OkResult.cs index af63b2de4..e99d68c15 100644 --- a/src/System.Web.Http/Results/OkResult.cs +++ b/src/System.Web.Http/Results/OkResult.cs @@ -14,14 +14,14 @@ public class OkResult : IHttpActionResult { private readonly StatusCodeResult.IDependencyProvider _dependencies; - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// The request message which led to this result. public OkResult(HttpRequestMessage request) : this(new StatusCodeResult.DirectDependencyProvider(request)) { } - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// The controller from which to obtain the dependencies needed for execution. public OkResult(ApiController controller) : this(new StatusCodeResult.ApiControllerDependencyProvider(controller)) diff --git a/src/System.Web.Http/Settings.StyleCop b/src/System.Web.Http/Settings.StyleCop deleted file mode 100644 index ddf8ec764..000000000 --- a/src/System.Web.Http/Settings.StyleCop +++ /dev/null @@ -1,11 +0,0 @@ - - - DynamicQueryable.cs - UriQueryUtility.cs - - - False - - - - \ No newline at end of file diff --git a/src/System.Web.Http/System.Web.Http.csproj b/src/System.Web.Http/System.Web.Http.csproj index e3a7de044..27041a371 100644 --- a/src/System.Web.Http/System.Web.Http.csproj +++ b/src/System.Web.Http/System.Web.Http.csproj @@ -14,12 +14,14 @@ 1591 - + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + False + @@ -100,9 +102,6 @@ Common\TypeExtensions.cs - - Common\UriQueryUtility.cs - @@ -267,7 +266,9 @@ + + diff --git a/src/System.Web.Http/Validation/BodyModelValidatorContext.cs b/src/System.Web.Http/Validation/BodyModelValidatorContext.cs new file mode 100644 index 000000000..9e34dcbf7 --- /dev/null +++ b/src/System.Web.Http/Validation/BodyModelValidatorContext.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Web.Http.Controllers; +using System.Web.Http.Metadata; +using System.Web.Http.ModelBinding; + +namespace System.Web.Http.Validation +{ + /// + /// Context passed between methods. + /// + public class BodyModelValidatorContext + { + public BodyModelValidatorContext(ModelStateDictionary modelState) + { + if (modelState == null) + { + throw new ArgumentNullException("modelState"); + } + + KeyBuilders = new Stack(); + ModelState = modelState; + Visited = new HashSet(ReferenceEqualityComparer.Instance); + } + + /// + /// Gets or sets the used to provide the model metadata. + /// + public ModelMetadataProvider MetadataProvider { get; set; } + + /// + /// Gets or sets the within which the model is being validated. + /// + public HttpActionContext ActionContext { get; set; } + + /// + /// Gets or sets the . + /// + public IModelValidatorCache ValidatorCache { get; set; } + + /// + /// Gets the current . + /// + public ModelStateDictionary ModelState { get; private set; } + + /// + /// Gets the set of model objects visited in this validation. Includes the model being validated in the + /// current scope. + /// + public HashSet Visited { get; private set; } + + /// + /// Gets the stack of s used in this validation. Includes + /// the to generate model state keys for the current scope. + /// + public Stack KeyBuilders { get; private set; } + + /// + /// Gets or sets the model state prefix for the root scope of this validation. + /// + public string RootPrefix { get; set; } + } +} diff --git a/src/System.Web.Http/Validation/DefaultBodyModelValidator.cs b/src/System.Web.Http/Validation/DefaultBodyModelValidator.cs index 60a092b8f..78ba06803 100644 --- a/src/System.Web.Http/Validation/DefaultBodyModelValidator.cs +++ b/src/System.Web.Http/Validation/DefaultBodyModelValidator.cs @@ -16,15 +16,10 @@ namespace System.Web.Http.Validation { /// - /// Recursively validate an object. + /// Recursively validate an object. /// public class DefaultBodyModelValidator : IBodyModelValidator { - private interface IKeyBuilder - { - string AppendTo(string prefix); - } - /// /// Determines whether the is valid and adds any validation errors to the 's /// @@ -64,14 +59,11 @@ public bool Validate(object model, Type type, ModelMetadataProvider metadataProv } ModelMetadata metadata = metadataProvider.GetMetadataForType(() => model, type); - ValidationContext validationContext = new ValidationContext() + BodyModelValidatorContext validationContext = new BodyModelValidatorContext(actionContext.ModelState) { MetadataProvider = metadataProvider, ActionContext = actionContext, ValidatorCache = actionContext.GetValidatorCache(), - ModelState = actionContext.ModelState, - Visited = new HashSet(ReferenceEqualityComparer.Instance), - KeyBuilders = new Stack(), RootPrefix = keyPrefix }; return ValidateNodeAndChildren(metadata, validationContext, container: null, validators: null); @@ -87,12 +79,36 @@ public virtual bool ShouldValidateType(Type type) return !MediaTypeFormatterCollection.IsTypeExcludedFromValidation(type); } + /// + /// Recursively validate the given and . + /// + /// The for the object to validate. + /// The . + /// The object containing the object to validate. + /// The collection of s. + /// + /// if validation succeeds for the given , + /// , and child nodes; otherwise. + /// [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "See comment below")] - private bool ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, object container, IEnumerable validators) + protected virtual bool ValidateNodeAndChildren( + ModelMetadata metadata, + BodyModelValidatorContext validationContext, + object container, + IEnumerable validators) { // Recursion guard to avoid stack overflows RuntimeHelpers.EnsureSufficientExecutionStack(); + if (metadata == null) + { + throw Error.ArgumentNull("metadata"); + } + if (validationContext == null) + { + throw Error.ArgumentNull("validationContext"); + } + object model = null; try { @@ -155,8 +171,26 @@ private bool ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext v return isValid; } - private bool ValidateProperties(ModelMetadata metadata, ValidationContext validationContext) + /// + /// Recursively validate the properties of the given . + /// + /// The for the object to validate. + /// The . + /// + /// if validation succeeds for all properties in ; + /// otherwise. + /// + protected virtual bool ValidateProperties(ModelMetadata metadata, BodyModelValidatorContext validationContext) { + if (metadata == null) + { + throw Error.ArgumentNull("metadata"); + } + if (validationContext == null) + { + throw Error.ArgumentNull("validationContext"); + } + bool isValid = true; PropertyScope propertyScope = new PropertyScope(); validationContext.KeyBuilders.Push(propertyScope); @@ -172,8 +206,26 @@ private bool ValidateProperties(ModelMetadata metadata, ValidationContext valida return isValid; } - private bool ValidateElements(IEnumerable model, ValidationContext validationContext) + /// + /// Recursively validate the elements of the collection. + /// + /// The instance containing the elements to validate. + /// The . + /// + /// if validation succeeds for all elements of ; + /// otherwise. + /// + protected virtual bool ValidateElements(IEnumerable model, BodyModelValidatorContext validationContext) { + if (model == null) + { + throw Error.ArgumentNull("model"); + } + if (validationContext == null) + { + throw Error.ArgumentNull("validationContext"); + } + bool isValid = true; Type elementType = GetElementType(model.GetType()); ModelMetadata elementMetadata = validationContext.MetadataProvider.GetMetadataForType(null, elementType); @@ -207,15 +259,39 @@ private bool ValidateElements(IEnumerable model, ValidationContext validationCon return isValid; } - // Validates a single node (not including children) - // Returns true if validation passes successfully - private static bool ShallowValidate(ModelMetadata metadata, ValidationContext validationContext, object container, IEnumerable validators) + /// + /// Validate a single node, not including its children. + /// + /// The . + /// The . + /// The object to validate. + /// The collection of s. + /// + /// if validation succeeds for the given and + /// ; otherwise. + /// + protected virtual bool ShallowValidate( + ModelMetadata metadata, + BodyModelValidatorContext validationContext, + object container, + IEnumerable validators) { + if (metadata == null) + { + throw Error.ArgumentNull("metadata"); + } + if (validationContext == null) + { + throw Error.ArgumentNull("validationContext"); + } + if (validators == null) + { + throw Error.ArgumentNull("validators"); + } + bool isValid = true; string modelKey = null; - Contract.Assert(validators != null); - // When the are no validators we bail quickly. This saves a GetEnumerator allocation. // In a large array (tens of thousands or more) scenario it's very significant. ICollection validatorsAsCollection = validators as ICollection; @@ -231,7 +307,7 @@ private static bool ShallowValidate(ModelMetadata metadata, ValidationContext va if (modelKey == null) { modelKey = validationContext.RootPrefix; - foreach (IKeyBuilder keyBuilder in validationContext.KeyBuilders.Reverse()) + foreach (IBodyModelValidatorKeyBuilder keyBuilder in validationContext.KeyBuilders.Reverse()) { modelKey = keyBuilder.AppendTo(modelKey); } @@ -263,7 +339,7 @@ private static Type GetElementType(Type type) return typeof(object); } - private class PropertyScope : IKeyBuilder + private class PropertyScope : IBodyModelValidatorKeyBuilder { public string PropertyName { get; set; } @@ -273,7 +349,7 @@ public string AppendTo(string prefix) } } - private class ElementScope : IKeyBuilder + private class ElementScope : IBodyModelValidatorKeyBuilder { public int Index { get; set; } @@ -282,16 +358,5 @@ public string AppendTo(string prefix) return ModelBindingHelper.CreateIndexModelName(prefix, Index); } } - - private class ValidationContext - { - public ModelMetadataProvider MetadataProvider { get; set; } - public HttpActionContext ActionContext { get; set; } - public IModelValidatorCache ValidatorCache { get; set; } - public ModelStateDictionary ModelState { get; set; } - public HashSet Visited { get; set; } - public Stack KeyBuilders { get; set; } - public string RootPrefix { get; set; } - } } } diff --git a/src/System.Web.Http/Validation/IBodyModelValidatorKeyBuilder.cs b/src/System.Web.Http/Validation/IBodyModelValidatorKeyBuilder.cs new file mode 100644 index 000000000..a45a6b732 --- /dev/null +++ b/src/System.Web.Http/Validation/IBodyModelValidatorKeyBuilder.cs @@ -0,0 +1,19 @@ +// 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. + +namespace System.Web.Http.Validation +{ + /// + /// Abstraction for creating keys used in nested validation scopes. Intended for use in + /// implementations, especially . + /// + public interface IBodyModelValidatorKeyBuilder + { + /// + /// Returns the key for a nested scope within the scope. + /// + /// Key for the current scope. + /// Key for a nested scope. Usually appends a property name to . + string AppendTo(string prefix); + } +} diff --git a/src/System.Web.Http/Validation/IModelValidatorCache.cs b/src/System.Web.Http/Validation/IModelValidatorCache.cs index f7b84e37c..81bcba823 100644 --- a/src/System.Web.Http/Validation/IModelValidatorCache.cs +++ b/src/System.Web.Http/Validation/IModelValidatorCache.cs @@ -1,16 +1,21 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Collections.Generic; using System.Web.Http.Metadata; namespace System.Web.Http.Validation { /// - /// Defines a cache for s. This cache is keyed on the type or property that the metadata is associated with. + /// Defines a cache for s. This cache is keyed on the type or property that the + /// metadata is associated with. /// - internal interface IModelValidatorCache + public interface IModelValidatorCache { + /// + /// Returns the s for the given . + /// + /// The . + /// An array of s for the given . ModelValidator[] GetValidators(ModelMetadata metadata); } } diff --git a/src/System.Web.Http/Validation/Validators/DataAnnotationsModelValidator.cs b/src/System.Web.Http/Validation/Validators/DataAnnotationsModelValidator.cs index 0e7620d7e..4f8895879 100644 --- a/src/System.Web.Http/Validation/Validators/DataAnnotationsModelValidator.cs +++ b/src/System.Web.Http/Validation/Validators/DataAnnotationsModelValidator.cs @@ -2,7 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Collections.Specialized; using System.ComponentModel.DataAnnotations; +using System.Configuration; using System.Linq; using System.Web.Http.Metadata; @@ -10,7 +12,13 @@ namespace System.Web.Http.Validation.Validators { public class DataAnnotationsModelValidator : ModelValidator { - public DataAnnotationsModelValidator(IEnumerable validatorProviders, ValidationAttribute attribute) + internal static readonly string UseLegacyValidationMemberNameKey = "webapi:UseLegacyValidationMemberName"; + private static bool _useLegacyValidationMemberName = + GetUseLegacyValidationMemberName(ConfigurationManager.AppSettings); + + public DataAnnotationsModelValidator( + IEnumerable validatorProviders, + ValidationAttribute attribute) : base(validatorProviders) { if (attribute == null) @@ -21,6 +29,13 @@ public DataAnnotationsModelValidator(IEnumerable validat Attribute = attribute; } + // Internal for testing + internal static bool UseLegacyValidationMemberName + { + get { return _useLegacyValidationMemberName; } + set { _useLegacyValidationMemberName = value; } + } + protected internal ValidationAttribute Attribute { get; private set; } public override bool IsRequired @@ -30,25 +45,39 @@ public override bool IsRequired public override IEnumerable Validate(ModelMetadata metadata, object container) { + string memberName; + if (_useLegacyValidationMemberName) + { + // Using member name from a Display or DisplayFormat attribute is generally incorrect. This + // (configuration-controlled) override is provided only for corner cases where strict + // back-compatibility is required. + memberName = metadata.GetDisplayName(); + } + else + { + // MemberName expression matches GetDisplayName() except it ignores Display and DisplayName + // attributes. ModelType fallback isn't great and can separate errors and attempted values in the + // ModelState. But, expression matches MVC, avoids a null MemberName, and is mostly back-compatible. + memberName = metadata.PropertyName ?? metadata.ModelType.Name; + } + // Per the WCF RIA Services team, instance can never be null (if you have // no parent, you pass yourself for the "instance" parameter). - - string memberName = metadata.GetDisplayName(); - ValidationContext context = new ValidationContext(container ?? metadata.Model) + ValidationContext context = new ValidationContext(instance: container ?? metadata.Model) { - DisplayName = memberName, - MemberName = memberName + DisplayName = metadata.GetDisplayName(), + MemberName = memberName, }; ValidationResult result = Attribute.GetValidationResult(metadata.Model, context); if (result != ValidationResult.Success) { - // ModelValidationResult.MemberName is used by invoking validators (such as ModelValidationNode) to - // construct the ModelKey for ModelStateDictionary. When validating at type level we want to append the - // returned MemberNames if specified (e.g. person.Address.FirstName). For property validation, the - // ModelKey can be constructed using the ModelMetadata and we should ignore MemberName (we don't want - // (person.Name.Name). However the invoking validator does not have a way to distinguish between these two + // ModelValidationResult.MemberName is used by invoking validators (such as ModelValidationNode) to + // construct the ModelKey for ModelStateDictionary. When validating at type level we want to append the + // returned MemberNames if specified (e.g. person.Address.FirstName). For property validation, the + // ModelKey can be constructed using the ModelMetadata and we should ignore MemberName (we don't want + // (person.Name.Name). However the invoking validator does not have a way to distinguish between these two // cases. Consequently we'll only set MemberName if this validation returns a MemberName that is different // from the property being validated. @@ -63,11 +92,29 @@ public override IEnumerable Validate(ModelMetadata metada Message = result.ErrorMessage, MemberName = errorMemberName }; - + return new ModelValidationResult[] { validationResult }; } return Enumerable.Empty(); } + + // Internal for testing + internal static bool GetUseLegacyValidationMemberName(NameValueCollection appSettings) + { + var useLegacyMemberNameArray = appSettings.GetValues(UseLegacyValidationMemberNameKey); + if (useLegacyMemberNameArray != null && + useLegacyMemberNameArray.Length > 0) + { + bool useLegacyMemberName; + if (bool.TryParse(useLegacyMemberNameArray[0], out useLegacyMemberName) && + useLegacyMemberName) + { + return true; + } + } + + return false; + } } } diff --git a/src/System.Web.Http/packages.config b/src/System.Web.Http/packages.config index 992a6e6d0..093dcd239 100644 --- a/src/System.Web.Http/packages.config +++ b/src/System.Web.Http/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/System.Web.Mvc/DefaultControllerFactory.cs b/src/System.Web.Mvc/DefaultControllerFactory.cs index a92a90cd2..c277c071b 100644 --- a/src/System.Web.Mvc/DefaultControllerFactory.cs +++ b/src/System.Web.Mvc/DefaultControllerFactory.cs @@ -141,7 +141,8 @@ public virtual IController CreateController(RequestContext requestContext, strin throw new ArgumentNullException("requestContext"); } - if (String.IsNullOrEmpty(controllerName) && !requestContext.RouteData.HasDirectRouteMatch()) + if (String.IsNullOrEmpty(controllerName) && + (requestContext.RouteData == null || !requestContext.RouteData.HasDirectRouteMatch())) { throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName"); } @@ -153,6 +154,10 @@ public virtual IController CreateController(RequestContext requestContext, strin protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) { + if (requestContext == null) + { + throw new ArgumentNullException("requestContext"); + } if (controllerType == null) { throw new HttpException(404, @@ -170,6 +175,7 @@ protected internal virtual IController GetControllerInstance(RequestContext requ controllerType), "controllerType"); } + return ControllerActivator.Create(requestContext, controllerType); } @@ -214,7 +220,7 @@ protected internal virtual Type GetControllerType(RequestContext requestContext, // first search in the current route's namespace collection object routeNamespacesObj; Type match; - if (routeData.DataTokens.TryGetValue(RouteDataTokenKeys.Namespaces, out routeNamespacesObj)) + if (routeData != null && routeData.DataTokens.TryGetValue(RouteDataTokenKeys.Namespaces, out routeNamespacesObj)) { IEnumerable routeNamespaces = routeNamespacesObj as IEnumerable; if (routeNamespaces != null && routeNamespaces.Any()) @@ -232,10 +238,11 @@ protected internal virtual Type GetControllerType(RequestContext requestContext, } // then search in the application's default namespace collection + RouteBase route = routeData == null ? null : routeData.Route; if (ControllerBuilder.DefaultNamespaces.Count > 0) { HashSet namespaceDefaults = new HashSet(ControllerBuilder.DefaultNamespaces, StringComparer.OrdinalIgnoreCase); - match = GetControllerTypeWithinNamespaces(routeData.Route, controllerName, namespaceDefaults); + match = GetControllerTypeWithinNamespaces(route, controllerName, namespaceDefaults); if (match != null) { return match; @@ -243,7 +250,7 @@ protected internal virtual Type GetControllerType(RequestContext requestContext, } // if all else fails, search every namespace - return GetControllerTypeWithinNamespaces(routeData.Route, controllerName, null /* namespaces */); + return GetControllerTypeWithinNamespaces(route, controllerName, null /* namespaces */); } private static Type GetControllerTypeFromDirectRoute(RouteData routeData) diff --git a/src/System.Web.Mvc/ExpressionHelper.cs b/src/System.Web.Mvc/ExpressionHelper.cs index 99d0282e1..17c8cf35d 100644 --- a/src/System.Web.Mvc/ExpressionHelper.cs +++ b/src/System.Web.Mvc/ExpressionHelper.cs @@ -35,6 +35,7 @@ public static string GetExpressionText(LambdaExpression expression) if (!IsSingleArgumentIndexer(methodExpression)) { + // Unsupported break; } @@ -59,7 +60,18 @@ public static string GetExpressionText(LambdaExpression expression) else if (part.NodeType == ExpressionType.MemberAccess) { MemberExpression memberExpressionPart = (MemberExpression)part; - nameParts.Push("." + memberExpressionPart.Member.Name); + var name = memberExpressionPart.Member.Name; + + // If identifier contains "__", it is "reserved for use by the implementation" and likely compiler- + // or Razor-generated e.g. the name of a field in a delegate's generated class. + if (name.Contains("__")) + { + // Exit loop. Should have the entire name because previous MemberAccess has same name as the + // leftmost expression node (a variable). + break; + } + + nameParts.Push("." + name); part = memberExpressionPart.Expression; } else if (part.NodeType == ExpressionType.Parameter) @@ -69,15 +81,19 @@ public static string GetExpressionText(LambdaExpression expression) // string onto the stack and stop evaluating. The extra empty string makes sure that // we don't accidentally cut off too much of m => m.Model. nameParts.Push(String.Empty); - part = null; + + // Exit loop. Have the entire name because the parameter cannot be used as an indexer; always the + // leftmost expression node. + break; } else { + // Unsupported break; } } - // If it starts with "model", then strip that away + // If parts start with "model", then strip that part away. if (nameParts.Count > 0 && String.Equals(nameParts.Peek(), ".model", StringComparison.OrdinalIgnoreCase)) { nameParts.Pop(); diff --git a/src/System.Web.Mvc/Html/DefaultEditorTemplates.cs b/src/System.Web.Mvc/Html/DefaultEditorTemplates.cs index 1a54b54d0..0ff053c58 100644 --- a/src/System.Web.Mvc/Html/DefaultEditorTemplates.cs +++ b/src/System.Web.Mvc/Html/DefaultEditorTemplates.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.Linq; using System.Text; +using System.Web.Configuration; using System.Web.Mvc.Properties; using System.Web.Routing; using System.Web.UI.WebControls; @@ -18,6 +19,7 @@ namespace System.Web.Mvc.Html internal static class DefaultEditorTemplates { private const string HtmlAttributeKey = "htmlAttributes"; + private const string UsePasswordValue = "Switch.System.Web.Mvc.UsePasswordValue"; internal static string BooleanTemplate(HtmlHelper html) { @@ -149,11 +151,11 @@ internal static string HiddenInputTemplate(HtmlHelper html) MvcHtmlString hiddenResult; - if (htmlAttributesDict != null) + if (htmlAttributesDict != null) { hiddenResult = html.Hidden(String.Empty, model, htmlAttributesDict); - } - else + } + else { hiddenResult = html.Hidden(String.Empty, model, htmlAttributesObject); } @@ -178,9 +180,9 @@ private static IDictionary CreateHtmlAttributes(HtmlHelper html, { return MergeHtmlAttributes(htmlAttributesObject, className, inputType); } - + var htmlAttributes = new Dictionary() - { + { { "class", className } }; if (inputType != null) @@ -274,9 +276,21 @@ internal static string ObjectTemplate(HtmlHelper html, TemplateHelpers.TemplateH internal static string PasswordTemplate(HtmlHelper html) { - return html.Password(String.Empty, - html.ViewContext.ViewData.TemplateInfo.FormattedModelValue, - CreateHtmlAttributes(html, "text-box single-line password")).ToHtmlString(); + object value = null; + var usePasswordStrings = WebConfigurationManager.AppSettings.GetValues(UsePasswordValue); + bool usePasswordValue; + if (usePasswordStrings != null && + usePasswordStrings.Length > 0 && + bool.TryParse(usePasswordStrings[0], out usePasswordValue) && + usePasswordValue) + { + value = html.ViewContext.ViewData.TemplateInfo.FormattedModelValue; + } + + return html.Password( + name: String.Empty, + value: value, + htmlAttributes: CreateHtmlAttributes(html, "text-box single-line password")).ToHtmlString(); } private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo) diff --git a/src/System.Web.Mvc/Html/InputExtensions.cs b/src/System.Web.Mvc/Html/InputExtensions.cs index b52ee3157..315fb5a7a 100644 --- a/src/System.Web.Mvc/Html/InputExtensions.cs +++ b/src/System.Web.Mvc/Html/InputExtensions.cs @@ -358,7 +358,7 @@ private static MvcHtmlString RadioButtonHelper(HtmlHelper htmlHelper, ModelMetad { string valueString = Convert.ToString(value, CultureInfo.CurrentCulture); isChecked = model != null && - !String.IsNullOrEmpty(name) && + !String.IsNullOrEmpty(htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name)) && String.Equals(model.ToString(), valueString, StringComparison.OrdinalIgnoreCase); } diff --git a/src/System.Web.Mvc/Html/SelectExtensions.cs b/src/System.Web.Mvc/Html/SelectExtensions.cs index af4a6cbff..bc76a4bdd 100644 --- a/src/System.Web.Mvc/Html/SelectExtensions.cs +++ b/src/System.Web.Mvc/Html/SelectExtensions.cs @@ -285,7 +285,7 @@ private static MvcHtmlString ListBoxHelper(HtmlHelper htmlHelper, ModelMetadata private static IEnumerable GetSelectData(this HtmlHelper htmlHelper, string name) { object o = null; - if (htmlHelper.ViewData != null) + if (htmlHelper.ViewData != null && !String.IsNullOrEmpty(name)) { o = htmlHelper.ViewData.Eval(name); } @@ -396,9 +396,9 @@ private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMet // If we haven't already used ViewData to get the entire list of items then we need to // use the ViewData-supplied value before using the parameter-supplied value. - if (defaultValue == null && !String.IsNullOrEmpty(name)) + if (defaultValue == null) { - if (!usedViewData) + if (!usedViewData && !String.IsNullOrEmpty(name)) { defaultValue = htmlHelper.ViewData.Eval(name); } diff --git a/src/System.Web.Mvc/Properties/AssemblyInfo.cs b/src/System.Web.Mvc/Properties/AssemblyInfo.cs index 3972a6d66..15b19258a 100644 --- a/src/System.Web.Mvc/Properties/AssemblyInfo.cs +++ b/src/System.Web.Mvc/Properties/AssemblyInfo.cs @@ -4,7 +4,6 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Security; using System.Web; using System.Web.Mvc; @@ -12,6 +11,7 @@ [assembly: AssemblyDescription("System.Web.Mvc.dll")] [assembly: Guid("4b5f4208-c6b0-4c37-9a41-63325ffa52ad")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] [assembly: InternalsVisibleTo("System.Web.Mvc.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] [assembly: PreApplicationStartMethod(typeof(PreApplicationStartCode), "Start")] [assembly: TypeForwardedTo(typeof(TagBuilder))] diff --git a/src/System.Web.WebPages/Helpers/AntiXsrf/AntiForgeryWorker.cs b/src/System.Web.WebPages/Helpers/AntiXsrf/AntiForgeryWorker.cs index 00912eae3..96e15c3a1 100644 --- a/src/System.Web.WebPages/Helpers/AntiXsrf/AntiForgeryWorker.cs +++ b/src/System.Web.WebPages/Helpers/AntiXsrf/AntiForgeryWorker.cs @@ -104,7 +104,11 @@ public TagBuilder GetFormInputElement(HttpContextBase httpContext) // Adding X-Frame-Options header to prevent ClickJacking. See // http://tools.ietf.org/html/draft-ietf-websec-x-frame-options-10 // for more information. - httpContext.Response.AddHeader("X-Frame-Options", "SAMEORIGIN"); + const string FrameHeaderName = "X-Frame-Options"; + if (httpContext.Response.Headers[FrameHeaderName] == null) + { + httpContext.Response.AddHeader(FrameHeaderName, "SAMEORIGIN"); + } } // @@ -181,4 +185,4 @@ public void Validate(HttpContextBase httpContext, string cookieToken, string for _validator.ValidateTokens(httpContext, ExtractIdentity(httpContext), deserializedCookieToken, deserializedFormToken); } } -} \ No newline at end of file +} diff --git a/src/WebApiHelpPage/Areas/HelpPage/Views/Web.config b/src/WebApiHelpPage/Areas/HelpPage/Views/Web.config index e946f6a6c..5ce411ea8 100644 --- a/src/WebApiHelpPage/Areas/HelpPage/Views/Web.config +++ b/src/WebApiHelpPage/Areas/HelpPage/Views/Web.config @@ -9,7 +9,7 @@ - + diff --git a/src/WebApiHelpPage/VB/Areas/HelpPage/Views/Web.config b/src/WebApiHelpPage/VB/Areas/HelpPage/Views/Web.config index bc8f8d836..b44b016c0 100644 --- a/src/WebApiHelpPage/VB/Areas/HelpPage/Views/Web.config +++ b/src/WebApiHelpPage/VB/Areas/HelpPage/Views/Web.config @@ -9,7 +9,7 @@ - + diff --git a/src/WebApiHelpPage/VB/WebApiHelpPage.VB.nuspec b/src/WebApiHelpPage/VB/WebApiHelpPage.VB.nuspec index 2ec9914e6..3e826d647 100644 --- a/src/WebApiHelpPage/VB/WebApiHelpPage.VB.nuspec +++ b/src/WebApiHelpPage/VB/WebApiHelpPage.VB.nuspec @@ -7,8 +7,7 @@ Microsoft Microsoft http://www.asp.net/web-api - true - http://www.microsoft.com/web/webpi/eula/mvc4extensions_prerelease_eula.htm + The ASP.NET Web API Help Page automatically generates help page content for the web APIs on your site. Visitors to your help page can use this content to learn how to call your web APIs. Everything generated by the help page is fully customizable using ASP.NET MVC and Razor. ASP.NET Web API Help Page is a great addition to any ASP.NET Web API project. The ASP.NET Web API Help Page automatically generates help page content for the web APIs on your site. diff --git a/src/WebApiHelpPage/VB/WebApiHelpPageVB.vbproj b/src/WebApiHelpPage/VB/WebApiHelpPageVB.vbproj index 08421a56a..8ecb16787 100644 --- a/src/WebApiHelpPage/VB/WebApiHelpPageVB.vbproj +++ b/src/WebApiHelpPage/VB/WebApiHelpPageVB.vbproj @@ -42,9 +42,10 @@ On - + + ..\..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll False - ..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + False diff --git a/src/WebApiHelpPage/VB/packages.config b/src/WebApiHelpPage/VB/packages.config index 3cb4a4570..03c4ef519 100644 --- a/src/WebApiHelpPage/VB/packages.config +++ b/src/WebApiHelpPage/VB/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/WebApiHelpPage/WebApiHelpPage.csproj b/src/WebApiHelpPage/WebApiHelpPage.csproj index 0c051123c..be06fa908 100644 --- a/src/WebApiHelpPage/WebApiHelpPage.csproj +++ b/src/WebApiHelpPage/WebApiHelpPage.csproj @@ -15,9 +15,10 @@ 1591 - + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + False diff --git a/src/WebApiHelpPage/WebApiHelpPage.nuspec b/src/WebApiHelpPage/WebApiHelpPage.nuspec index 8bab28cb7..8c69a51b1 100644 --- a/src/WebApiHelpPage/WebApiHelpPage.nuspec +++ b/src/WebApiHelpPage/WebApiHelpPage.nuspec @@ -7,8 +7,7 @@ Microsoft Microsoft http://www.asp.net/web-api - true - http://www.microsoft.com/web/webpi/eula/mvc4extensions_prerelease_eula.htm + The ASP.NET Web API Help Page automatically generates help page content for the web APIs on your site. Visitors to your help page can use this content to learn how to call your web APIs. Everything generated by the help page is fully customizable using ASP.NET MVC and Razor. ASP.NET Web API Help Page is a great addition to any ASP.NET Web API project. The ASP.NET Web API Help Page automatically generates help page content for the web APIs on your site. diff --git a/src/WebApiHelpPage/WebApiHelpPageMsBuildTasks.targets b/src/WebApiHelpPage/WebApiHelpPageMsBuildTasks.targets index e9c9dc9d9..5a6a45245 100644 --- a/src/WebApiHelpPage/WebApiHelpPageMsBuildTasks.targets +++ b/src/WebApiHelpPage/WebApiHelpPageMsBuildTasks.targets @@ -1,13 +1,5 @@ - - $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll - $(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll - $(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll - Microsoft.Build.Tasks.Core - Microsoft.Build.Tasks.v$(MSBuildToolsVersion) - Microsoft.Build.Tasks.v4.0 - diff --git a/src/WebApiHelpPage/packages.config b/src/WebApiHelpPage/packages.config index 96befa888..6046c1be3 100644 --- a/src/WebApiHelpPage/packages.config +++ b/src/WebApiHelpPage/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/test/Common/AttributeListTest.cs b/test/Common/AttributeListTest.cs index 738928dae..5c5d12e3a 100644 --- a/test/Common/AttributeListTest.cs +++ b/test/Common/AttributeListTest.cs @@ -54,14 +54,14 @@ public void AttributeListClearThrows() public void AttributeListContainsWrappedTrue() { Attribute presentAttribute = _collection[2]; - Assert.True(_list.Contains(presentAttribute)); + Assert.Contains(presentAttribute, _list); } [Fact] public void AttributeListContainsMissingFalse() { Attribute missingAttribute = new MissingAttribute(); - Assert.False(_list.Contains(missingAttribute)); + Assert.DoesNotContain(missingAttribute, _list); } [Fact] diff --git a/test/Common/CollectionExtensionsTest.cs b/test/Common/CollectionExtensionsTest.cs index 927b74f83..e43ed456e 100644 --- a/test/Common/CollectionExtensionsTest.cs +++ b/test/Common/CollectionExtensionsTest.cs @@ -16,8 +16,8 @@ public void AppendAndReallocateEmpty_ReturnsOne() string[] emptyAppended = empty.AppendAndReallocate("AppendedEmpty"); - Assert.Equal(1, emptyAppended.Length); - Assert.Equal("AppendedEmpty", emptyAppended[0]); + string singleAppended = Assert.Single(emptyAppended); + Assert.Equal("AppendedEmpty", singleAppended); } [Fact] @@ -107,7 +107,7 @@ public void AsIList_Enumerable_Copies() Assert.Equal(expected, enumerableAsIList); Assert.NotSame(expected, enumerableAsIList); } - + [Fact] public void AsList_List_ReturnsSameInstance() { @@ -131,6 +131,7 @@ public void AsList_Enumerable_Copies() Assert.NotSame(array, arrayAsList); } + [Fact] public void AsList_ListWrapperCollection_ReturnsSameInstance() { List list = new List { new object(), new object() }; @@ -270,7 +271,7 @@ public void ToArrayWithoutNullsICollectionHasNullsRemovesNulls() Assert.Equal(hasNulls[2], hasNullsResult[1]); } - [Fact] + [Fact] public void ToDictionaryFastArray2Element() { string[] input = new string[] {"AA", "BB"}; @@ -283,7 +284,7 @@ public void ToDictionaryFastArray2Element() Assert.Equal(StringComparer.OrdinalIgnoreCase, result.Comparer); } - [Fact] + [Fact] public void ToDictionaryFastIListList2Element() { string[] input = new string[] {"AA", "BB"}; @@ -311,7 +312,7 @@ public void ToDictionaryFastIListArray2Element() Assert.Equal(StringComparer.OrdinalIgnoreCase, arrayResult.Comparer); } - [Fact] + [Fact] public void ToDictionaryFastIEnumerableArray2Element() { string[] input = new string[] {"AA", "BB"}; diff --git a/test/Common/Routing/DefaultInlineConstraintResolverTest.cs b/test/Common/Routing/DefaultInlineConstraintResolverTest.cs index 3597fec6b..8b7abbdeb 100644 --- a/test/Common/Routing/DefaultInlineConstraintResolverTest.cs +++ b/test/Common/Routing/DefaultInlineConstraintResolverTest.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Collections.Generic; #if ASPNETWEBAPI using System.Web.Http.Routing.Constraints; #else @@ -104,8 +103,8 @@ public void ResolveConstraint_LengthConstraint() { var constraint = new DefaultInlineConstraintResolver().ResolveConstraint("length(5)"); - Assert.IsType(constraint); - Assert.Equal(5, ((LengthRouteConstraint)constraint).Length); + var lengthRouteConstraint = Assert.IsType(constraint); + Assert.Equal(5, lengthRouteConstraint.Length); } [Fact] @@ -113,8 +112,7 @@ public void ResolveConstraint_LengthRangeConstraint() { var constraint = new DefaultInlineConstraintResolver().ResolveConstraint("length(5, 10)"); - Assert.IsType(constraint); - LengthRouteConstraint lengthConstraint = (LengthRouteConstraint)constraint; + LengthRouteConstraint lengthConstraint = Assert.IsType(constraint); Assert.Equal(5, lengthConstraint.MinLength); Assert.Equal(10, lengthConstraint.MaxLength); } @@ -132,8 +130,8 @@ public void ResolveConstraint_MaxConstraint() { var constraint = new DefaultInlineConstraintResolver().ResolveConstraint("max(10)"); - Assert.IsType(constraint); - Assert.Equal(10, ((MaxRouteConstraint)constraint).Max); + var maxRouteConstraint = Assert.IsType(constraint); + Assert.Equal(10, maxRouteConstraint.Max); } [Fact] @@ -141,8 +139,8 @@ public void ResolveConstraint_MaxLengthConstraint() { var constraint = new DefaultInlineConstraintResolver().ResolveConstraint("maxlength(10)"); - Assert.IsType(constraint); - Assert.Equal(10, ((MaxLengthRouteConstraint)constraint).MaxLength); + var maxLengthRouteConstraint = Assert.IsType(constraint); + Assert.Equal(10, maxLengthRouteConstraint.MaxLength); } [Fact] @@ -150,8 +148,8 @@ public void ResolveConstraint_MinConstraint() { var constraint = new DefaultInlineConstraintResolver().ResolveConstraint("min(3)"); - Assert.IsType(constraint); - Assert.Equal(3, ((MinRouteConstraint)constraint).Min); + var minRouteConstraint = Assert.IsType(constraint); + Assert.Equal(3, minRouteConstraint.Min); } [Fact] @@ -159,8 +157,8 @@ public void ResolveConstraint_MinLengthConstraint() { var constraint = new DefaultInlineConstraintResolver().ResolveConstraint("minlength(3)"); - Assert.IsType(constraint); - Assert.Equal(3, ((MinLengthRouteConstraint)constraint).MinLength); + var minLengthRouteConstraint = Assert.IsType(constraint); + Assert.Equal(3, minLengthRouteConstraint.MinLength); } [Fact] @@ -174,8 +172,7 @@ public void ResolveConstraint_RangeConstraint() { var constraint = new DefaultInlineConstraintResolver().ResolveConstraint("range(5, 10)"); - Assert.IsType(constraint); - RangeRouteConstraint rangeConstraint = (RangeRouteConstraint)constraint; + RangeRouteConstraint rangeConstraint = Assert.IsType(constraint); Assert.Equal(5, rangeConstraint.Min); Assert.Equal(10, rangeConstraint.Max); } @@ -185,8 +182,7 @@ public void ResolveConstraint_RegexConstraint() { var constraint = new DefaultInlineConstraintResolver().ResolveConstraint("regex(abc,defg)"); - Assert.IsType(constraint); - RegexRouteConstraint regexConstraint = (RegexRouteConstraint)constraint; + RegexRouteConstraint regexConstraint = Assert.IsType(constraint); Assert.Equal("abc,defg", regexConstraint.Pattern); } diff --git a/test/Common/Routing/InlineRouteTemplateParserTests.cs b/test/Common/Routing/InlineRouteTemplateParserTests.cs index 45c6a364d..49c3baebf 100644 --- a/test/Common/Routing/InlineRouteTemplateParserTests.cs +++ b/test/Common/Routing/InlineRouteTemplateParserTests.cs @@ -41,8 +41,8 @@ public void ParseRouteTemplate_ChainedConstraintWithArgumentsAndDefault() Assert.Equal("hello/{param}", result.RouteUrl); Assert.Equal("111111", result.Defaults["param"]); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"\d+", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var regexRouteConstraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\d+", regexRouteConstraint.Pattern); } [Fact] @@ -54,8 +54,7 @@ public void ParseRouteTemplate_ChainedConstraintAndOptional() Assert.Equal(OptionalParameter, result.Defaults["param"]); - Assert.IsType(result.Constraints["param"]); - var constraint = (OptionalRouteConstraint)result.Constraints["param"]; + var constraint = Assert.IsType(result.Constraints["param"]); Assert.IsType(constraint.InnerConstraint); } @@ -68,9 +67,8 @@ public void ParseRouteTemplate_ChainedConstraintWithArgumentsAndOptional() Assert.Equal(OptionalParameter, result.Defaults["param"]); - Assert.IsType(result.Constraints["param"]); - var constraint = (OptionalRouteConstraint)result.Constraints["param"]; - Assert.Equal(@"\d+", ((RegexRouteConstraint)constraint.InnerConstraint).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\d+", Assert.IsType(constraint.InnerConstraint).Pattern); } [Fact] @@ -80,10 +78,9 @@ public void ParseRouteTemplate_ChainedConstraints() Assert.Equal("hello/{param}", result.RouteUrl); - Assert.IsType(result.Constraints["param"]); - CompoundRouteConstraint constraint = (CompoundRouteConstraint)result.Constraints["param"]; - Assert.Equal(@"\d+", ((RegexRouteConstraint)constraint.Constraints.ElementAt(0)).Pattern); - Assert.Equal(@"\w+", ((RegexRouteConstraint)constraint.Constraints.ElementAt(1)).Pattern); + CompoundRouteConstraint constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\d+", Assert.IsType(constraint.Constraints.ElementAt(0)).Pattern); + Assert.Equal(@"\w+", Assert.IsType(constraint.Constraints.ElementAt(1)).Pattern); } [Fact] @@ -93,8 +90,8 @@ public void ParseRouteTemplate_Constraint() Assert.Equal("hello/{param}", result.RouteUrl); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"\d+", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\d+", constraint.Pattern); } [Fact] @@ -108,8 +105,7 @@ public void ParseRouteTemplate_ConstraintsDefaultsAndOptionalsInMultipleSections Assert.Equal("abc", result.Defaults["p2"]); Assert.Equal(OptionalParameter, result.Defaults["p3"]); - Assert.IsType(result.Constraints["p1"]); - CompoundRouteConstraint constraint = (CompoundRouteConstraint)result.Constraints["p1"]; + CompoundRouteConstraint constraint = Assert.IsType(result.Constraints["p1"]); Assert.IsType(constraint.Constraints.ElementAt(0)); Assert.IsType(constraint.Constraints.ElementAt(1)); } @@ -147,8 +143,8 @@ public void ParseRouteTemplate_RegexConstraintWithClosingBraceInPattern() Assert.Equal("hello/{param}", result.RouteUrl); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"\}", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\}", constraint.Pattern); } [Fact] @@ -158,8 +154,8 @@ public void ParseRouteTemplate_RegexConstraintWithClosingParenInPattern() Assert.Equal("hello/{param}", result.RouteUrl); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"\)", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\)", constraint.Pattern); } [Fact] @@ -168,8 +164,8 @@ public void ParseRouteTemplate_RegexConstraintWithColonInPattern() var result = Act(@"hello/{param:regex(:)}"); Assert.Equal("hello/{param}", result.RouteUrl); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@":", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@":", constraint.Pattern); } [Fact] @@ -178,8 +174,8 @@ public void ParseRouteTemplate_RegexConstraintWithCommaInPattern() var result = Act(@"hello/{param:regex(\w,\w)}"); Assert.Equal("hello/{param}", result.RouteUrl); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"\w,\w", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\w,\w", constraint.Pattern); } [Fact] @@ -190,8 +186,8 @@ public void ParseRouteTemplate_RegexConstraintWithEqualsSignInPattern() Assert.Equal("hello/{param}", result.RouteUrl); Assert.DoesNotContain("param", result.Defaults.Keys); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"=", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"=", constraint.Pattern); } [Fact] @@ -200,8 +196,8 @@ public void ParseRouteTemplate_RegexConstraintWithOpenBraceInPattern() var result = Act(@"hello/{param:regex(\{)}"); Assert.Equal("hello/{param}", result.RouteUrl); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"\{", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\{", constraint.Pattern); } [Fact] @@ -210,8 +206,8 @@ public void ParseRouteTemplate_RegexConstraintWithOpenParenInPattern() var result = Act(@"hello/{param:regex(\()}"); Assert.Equal("hello/{param}", result.RouteUrl); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"\(", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\(", constraint.Pattern); } [Fact] @@ -221,8 +217,8 @@ public void ParseRouteTemplate_RegexConstraintWithQuestionMarkInPattern() Assert.Equal("hello/{param}", result.RouteUrl); Assert.DoesNotContain("param", result.Defaults.Keys); - Assert.IsType(result.Constraints["param"]); - Assert.Equal(@"\?", ((RegexRouteConstraint)result.Constraints["param"]).Pattern); + var constraint = Assert.IsType(result.Constraints["param"]); + Assert.Equal(@"\?", constraint.Pattern); } diff --git a/test/Common/Routing/RouteFactoryAttributeTests.cs b/test/Common/Routing/RouteFactoryAttributeTests.cs index e313cd378..da02d84c7 100644 --- a/test/Common/Routing/RouteFactoryAttributeTests.cs +++ b/test/Common/Routing/RouteFactoryAttributeTests.cs @@ -500,8 +500,8 @@ public void AttributeUsage_IsAsSpecified() // Assert Assert.NotNull(usage); Assert.Equal(AttributeTargets.Class | AttributeTargets.Method, usage.ValidOn); - Assert.Equal(false, usage.Inherited); - Assert.Equal(true, usage.AllowMultiple); + Assert.False(usage.Inherited); + Assert.True(usage.AllowMultiple); } private static IDirectRouteBuilder CreateBuilder(Func build) diff --git a/test/Common/UriQueryUtilityTest.cs b/test/Common/UriQueryUtilityTest.cs index 8e094b2d1..ac0307cae 100644 --- a/test/Common/UriQueryUtilityTest.cs +++ b/test/Common/UriQueryUtilityTest.cs @@ -10,7 +10,7 @@ namespace System.Net.Http { - public class UriQueryUtilityTest + public class WebUtilityTest { public static TheoryDataSet UriQueryData { @@ -23,19 +23,20 @@ public static TheoryDataSet UriQueryData [Fact] public void TypeIsCorrect() { - Assert.Type.HasProperties(typeof(UriQueryUtility), TypeAssert.TypeProperties.IsClass | TypeAssert.TypeProperties.IsStatic); + Assert.Type.HasProperties(typeof(WebUtility), + TypeAssert.TypeProperties.IsStatic | TypeAssert.TypeProperties.IsPublicVisibleClass); } [Fact] public void UrlEncode_ReturnsNull() { - Assert.Null(UriQueryUtility.UrlEncode(null)); + Assert.Null(WebUtility.UrlEncode(null)); } [Fact] public void UrlDecode_ReturnsNull() { - Assert.Null(UriQueryUtility.UrlDecode(null)); + Assert.Null(WebUtility.UrlDecode(null)); } [Fact] @@ -52,12 +53,12 @@ public void UrlDecode_ParsesEmptySegmentsCorrectly() Assert.NotNull(result); // Because this is a NameValueCollection, the same name appears only once - Assert.Equal(1, result.Count); + Assert.Single(result); // Values should be a comma separated list of empty strings string[] values = result[""].Split(new char[] { ',' }); - // We expect length+1 segment as the final '&' counts as a segment + // We expect length+1 segment as the final '&' counts as a segment Assert.Equal(index + 1, values.Length); foreach (var value in values) { @@ -84,7 +85,7 @@ public void UrlDecode_ParsesCorrectly(string segment, string resultName, string Assert.NotNull(result); // Because this is a NameValueCollection, the same name appears only once - Assert.Equal(1, result.Count); + Assert.Single(result); // Values should be a comma separated list of resultValue string[] values = result[resultName].Split(new char[] { ',' }); diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 000000000..c55ba298d --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,12 @@ + + + + + false + true + v4.6.2 + + diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets new file mode 100644 index 000000000..99772c023 --- /dev/null +++ b/test/Directory.Build.targets @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Microsoft.AspNet.Facebook.Test/App.config b/test/Microsoft.AspNet.Facebook.Test/App.config index 6d1bb6403..e6cf76c59 100644 --- a/test/Microsoft.AspNet.Facebook.Test/App.config +++ b/test/Microsoft.AspNet.Facebook.Test/App.config @@ -1,4 +1,4 @@ - + diff --git a/test/Microsoft.AspNet.Facebook.Test/FacebookAuthorizeFilterHookTest.cs b/test/Microsoft.AspNet.Facebook.Test/FacebookAuthorizeFilterHookTest.cs index f8f3f9f8d..89a2e38a9 100644 --- a/test/Microsoft.AspNet.Facebook.Test/FacebookAuthorizeFilterHookTest.cs +++ b/test/Microsoft.AspNet.Facebook.Test/FacebookAuthorizeFilterHookTest.cs @@ -169,7 +169,7 @@ public void OnAuthorization_TriggersDeniedHookAfterPersistingRequestedPermission } // Assert - Assert.Equal(false, authorizeFilter.DeniedPermissionPromptHookTriggered); + Assert.False(authorizeFilter.DeniedPermissionPromptHookTriggered); // Act 2 // We're making a "second" request essentially diff --git a/test/Microsoft.AspNet.Facebook.Test/Microsoft.AspNet.Facebook.Test.csproj b/test/Microsoft.AspNet.Facebook.Test/Microsoft.AspNet.Facebook.Test.csproj index 916a598c4..bedf43f90 100644 --- a/test/Microsoft.AspNet.Facebook.Test/Microsoft.AspNet.Facebook.Test.csproj +++ b/test/Microsoft.AspNet.Facebook.Test/Microsoft.AspNet.Facebook.Test.csproj @@ -1,6 +1,7 @@  - + + {C3BEF382-C7C4-454D-B017-1EAC03E9A82C} @@ -13,40 +14,41 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - ..\..\packages\Facebook.6.1.4\lib\net45\Facebook.dll + ..\..\packages\Facebook.6.4.2\lib\net45\Facebook.dll - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True - - False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + True + - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -126,14 +128,20 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + - + obj\ns1_3\ + $(DefaultItemExcludes);obj\** + + diff --git a/test/Microsoft.TestCommon/ExceptionAssertions.cs b/test/Microsoft.TestCommon/ExceptionAssertions.cs index 1d21f04f0..9c0de771a 100644 --- a/test/Microsoft.TestCommon/ExceptionAssertions.cs +++ b/test/Microsoft.TestCommon/ExceptionAssertions.cs @@ -6,6 +6,9 @@ using System.Reflection; using System.Threading.Tasks; using System.Web; +#if Testing_NetStandard1_3 +using System.Web.Http; +#endif namespace Microsoft.TestCommon { @@ -294,7 +297,7 @@ public static async Task ThrowsArgumentNullAsync(FuncThrown when an exception was not thrown, or when an exception of the incorrect type is thrown public static ArgumentException ThrowsArgumentNullOrEmpty(Action testCode, string paramName) { - return Throws(testCode, "Value cannot be null or empty.\r\nParameter name: " + paramName, allowDerivedExceptions: false); + return Throws(testCode, "Value cannot be null or empty." + GetParameterMessage(paramName), allowDerivedExceptions: false); } /// @@ -324,7 +327,7 @@ public static ArgumentOutOfRangeException ThrowsArgumentOutOfRange(Action testCo { if (exceptionMessage != null) { - exceptionMessage = exceptionMessage + "\r\nParameter name: " + paramName; + exceptionMessage = exceptionMessage + GetParameterMessage(paramName); if (actualValue != null) { exceptionMessage += String.Format(CultureReplacer.DefaultCulture, "\r\nActual value was {0}.", actualValue); @@ -357,7 +360,7 @@ public static async Task ThrowsArgumentOutOfRangeAs { if (exceptionMessage != null) { - exceptionMessage = exceptionMessage + "\r\nParameter name: " + paramName; + exceptionMessage = exceptionMessage + GetParameterMessage(paramName); if (actualValue != null) { exceptionMessage += String.Format(CultureReplacer.DefaultCulture, "\r\nActual value was {0}.", actualValue); @@ -466,6 +469,7 @@ public static ArgumentOutOfRangeException ThrowsArgumentLessThanOrEqualTo(Action String.Format(CultureReplacer.DefaultCulture, "Value must be less than or equal to {0}.", maxValue), false, actualValue); } +#if !NETCOREAPP /// /// Verifies that the code throws an HttpException (or optionally any exception which derives from it). /// @@ -481,6 +485,7 @@ public static HttpException ThrowsHttpException(Action testCode, string exceptio Equal(httpCode, ex.GetHttpCode()); return ex; } +#endif /// /// Verifies that the code throws an InvalidEnumArgumentException (or optionally any exception which derives from it). @@ -492,12 +497,17 @@ public static HttpException ThrowsHttpException(Action testCode, string exceptio /// Pass true to allow exceptions which derive from TException; pass false, otherwise /// The exception that was thrown, when successful /// Thrown when an exception was not thrown, or when an exception of the incorrect type is thrown - public static InvalidEnumArgumentException ThrowsInvalidEnumArgument(Action testCode, string paramName, int invalidValue, Type enumType, bool allowDerivedExceptions = false) + public static ArgumentException ThrowsInvalidEnumArgument(Action testCode, string paramName, int invalidValue, Type enumType, bool allowDerivedExceptions = false) { string message = String.Format(CultureReplacer.DefaultCulture, - "The value of argument '{0}' ({1}) is invalid for Enum type '{2}'.{3}Parameter name: {0}", - paramName, invalidValue, enumType.Name, Environment.NewLine); + "The value of argument '{0}' ({1}) is invalid for Enum type '{2}'.{3}", + paramName, invalidValue, enumType.Name, GetParameterMessage(paramName)); + +#if Testing_NetStandard1_3 // InvalidEnumArgumentException not available in netstandard1.3. + return Throws(testCode, message, allowDerivedExceptions); +#else return Throws(testCode, message, allowDerivedExceptions); +#endif } /// @@ -571,6 +581,15 @@ public static async Task ThrowsAsync( return ex; } + private static string GetParameterMessage(string parameterName) + { +#if NETCOREAPP3_1_OR_GREATER + return " (Parameter '" + parameterName + "')"; +#else + return Environment.NewLine + "Parameter name: " + parameterName; +#endif + } + // We've re-implemented all the xUnit.net Throws code so that we can get this // updated implementation of RecordException which silently unwraps any instances // of AggregateException. In addition to unwrapping exceptions, this method ensures diff --git a/test/Microsoft.TestCommon/FactDiscoverer.cs b/test/Microsoft.TestCommon/FactDiscoverer.cs index db913e188..4be650293 100644 --- a/test/Microsoft.TestCommon/FactDiscoverer.cs +++ b/test/Microsoft.TestCommon/FactDiscoverer.cs @@ -76,6 +76,7 @@ public override IEnumerable Discover( var testCase = new SkippedXunitTestCase( _diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), + TestMethodDisplayOptions.None, skipReason, baseCase.TestMethod, baseCase.TestMethodArguments); diff --git a/test/Microsoft.TestCommon/Microsoft.TestCommon.csproj b/test/Microsoft.TestCommon/Microsoft.TestCommon.csproj index 4638df974..d22704250 100644 --- a/test/Microsoft.TestCommon/Microsoft.TestCommon.csproj +++ b/test/Microsoft.TestCommon/Microsoft.TestCommon.csproj @@ -1,120 +1,39 @@ - - + - {FCCC4CB7-BAF7-4A57-9F89-E5766FE536C0} - Library - Properties - Microsoft.TestCommon - Microsoft.TestCommon + net462;netcoreapp2.1;net6.0 + $(Configurations);CodeAnalysis + $(DefineConstants);Testing_NetStandard1_3 + false ..\..\bin\$(Configuration)\Test\ + $(OutputPath)ns1_3\ + - - - - - - - - - - - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll - True - - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll - True - - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll - True - - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll - True - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - Code - - - - - - - - Code - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - - - - - - \ No newline at end of file + diff --git a/test/Microsoft.TestCommon/Microsoft/TestCommon/DataSets/TestData.cs b/test/Microsoft.TestCommon/Microsoft/TestCommon/DataSets/TestData.cs index 6f0cc052a..6efc6f984 100644 --- a/test/Microsoft.TestCommon/Microsoft/TestCommon/DataSets/TestData.cs +++ b/test/Microsoft.TestCommon/Microsoft/TestCommon/DataSets/TestData.cs @@ -368,7 +368,6 @@ public abstract class TestData : TestData, IEnumerable private static readonly Type OpenIQueryableType = typeof(IQueryable<>); private static readonly Type OpenDictionaryType = typeof(Dictionary<,>); private static readonly Type OpenTestDataHolderType = typeof(TestDataHolder<>); - private int dictionaryKey; /// /// Initializes a new instance of the class. @@ -444,9 +443,9 @@ public IQueryable GetTestDataAsIQueryable() public Dictionary GetTestDataAsDictionary() { // Some TestData collections contain duplicates e.g. UintTestData contains both 0 and UInt32.MinValue. - // Therefore use dictionaryKey, not _unused.ToString(). Reset key to keep dictionaries consistent if used - // multiple times. - dictionaryKey = 0; + // Therefore use dictionaryKey, not _unused.ToString(). Do not reuse key to keep dictionaries consistent + // if enumerated multiple times. + int dictionaryKey = 0; return this.GetTypedTestData().ToDictionary(_unused => (dictionaryKey++).ToString()); } diff --git a/test/Microsoft.TestCommon/Microsoft/TestCommon/GenericTypeAssert.cs b/test/Microsoft.TestCommon/Microsoft/TestCommon/GenericTypeAssert.cs index f6ac8a164..d37b5d03e 100644 --- a/test/Microsoft.TestCommon/Microsoft/TestCommon/GenericTypeAssert.cs +++ b/test/Microsoft.TestCommon/Microsoft/TestCommon/GenericTypeAssert.cs @@ -178,7 +178,7 @@ public T InvokeConstructor(Type genericBaseType, Type[] genericParameterTypes /// An instance of type . public T InvokeConstructor(Type genericBaseType, Type genericParameterType, params object[] parameterValues) { - Assert.NotNull(genericBaseType == null); + Assert.NotNull(genericBaseType); Assert.True(genericBaseType.IsGenericTypeDefinition); Assert.NotNull(genericParameterType); @@ -217,14 +217,14 @@ public T InvokeConstructor(Type genericBaseType, Type[] genericParameterTypes /// The type of instance. /// The instance to test. /// The type of the generic parameter to which the instance's generic type should have been bound. - public void IsCorrectGenericType(T instance, Type genericTypeParameter) + public void IsCorrectGenericType(T instance, Type genericTypeParameter) where T : class { Assert.NotNull(instance); Assert.NotNull(genericTypeParameter); Assert.True(instance.GetType().IsGenericType); Type[] genericArguments = instance.GetType().GetGenericArguments(); - Assert.Equal(1, genericArguments.Length); - Assert.Equal(genericTypeParameter, genericArguments[0]); + Type genericArgument = Assert.Single(genericArguments); + Assert.Equal(genericTypeParameter, genericArgument); } /// diff --git a/test/Microsoft.TestCommon/Microsoft/TestCommon/HttpAssert.cs b/test/Microsoft.TestCommon/Microsoft/TestCommon/HttpAssert.cs index c1684c486..cb33f030c 100644 --- a/test/Microsoft.TestCommon/Microsoft/TestCommon/HttpAssert.cs +++ b/test/Microsoft.TestCommon/Microsoft/TestCommon/HttpAssert.cs @@ -109,8 +109,6 @@ public void Equal(HttpHeaders expectedHeaders, HttpHeaders actualHeaders) foreach (KeyValuePair> expectedHeader in expectedHeaders) { KeyValuePair> actualHeader = actualHeaders.FirstOrDefault(h => h.Key == expectedHeader.Key); - Assert.NotNull(actualHeader); - if (expectedHeader.Key == "Date") { HandleDateHeader(expectedHeader.Value.ToArray(), actualHeader.Value.ToArray()); diff --git a/test/Microsoft.TestCommon/PlatformInfo.cs b/test/Microsoft.TestCommon/PlatformInfo.cs index ee36ccb18..e3026e39e 100644 --- a/test/Microsoft.TestCommon/PlatformInfo.cs +++ b/test/Microsoft.TestCommon/PlatformInfo.cs @@ -11,6 +11,7 @@ namespace Microsoft.TestCommon public static class PlatformInfo { private const string _net45TypeName = "System.IWellKnownStringEqualityComparer, mscorlib, Version=4.0.0.0, PublicKeyToken=b77a5c561934e089"; + private const string _netCore20TypeName = "System.OrdinalCaseSensitiveComparer, system.private.corelib, Version=4.0.0.0, PublicKeyToken=7cec85d7bea7798e"; private static Lazy _platform = new Lazy(GetPlatform, isThreadSafe: true); /// @@ -23,6 +24,12 @@ public static Platform Platform private static Platform GetPlatform() { + if (Type.GetType(_netCore20TypeName, throwOnError: false) != null) + { + // Treat .NET Core 2.1 as a .NET 4.5 superset though internal types are different. + return Platform.Net45; + } + if (Type.GetType(_net45TypeName, throwOnError: false) != null) { return Platform.Net45; diff --git a/test/Microsoft.TestCommon/PortReserver.cs b/test/Microsoft.TestCommon/PortReserver.cs index a84ed27df..bfa95d610 100644 --- a/test/Microsoft.TestCommon/PortReserver.cs +++ b/test/Microsoft.TestCommon/PortReserver.cs @@ -5,12 +5,18 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; +using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Threading; namespace Microsoft.TestCommon { + [Xunit.CollectionDefinition("PortReserver Collection", DisableParallelization = true)] + public class PortReserverCollection + { + } + /// /// This class allocates ports while ensuring that: /// 1. Ports that are permanently taken (or taken for the duration of the test) are not being attempted to be used. @@ -154,7 +160,9 @@ private static IPEndPoint[] ListUsedTCPPort() { IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties(); - return ipGlobalProperties.GetActiveTcpListeners(); + return ipGlobalProperties.GetActiveTcpListeners() + .Concat(ipGlobalProperties.GetActiveUdpListeners()) + .ToArray(); } } } diff --git a/test/Microsoft.TestCommon/SkippedXunitTestCase.cs b/test/Microsoft.TestCommon/SkippedXunitTestCase.cs index e055b1e67..b5d536d3a 100644 --- a/test/Microsoft.TestCommon/SkippedXunitTestCase.cs +++ b/test/Microsoft.TestCommon/SkippedXunitTestCase.cs @@ -29,10 +29,11 @@ public class SkippedXunitTestCase : XunitTestCase public SkippedXunitTestCase( IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, + TestMethodDisplayOptions defaultMethodDisplayOptions, String skipReason, ITestMethod testMethod, object[] testMethodArguments = null) - : base(diagnosticMessageSink, defaultMethodDisplay, testMethod, testMethodArguments) + : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod, testMethodArguments) { _skipReason = skipReason; } diff --git a/test/Microsoft.TestCommon/TheoryDiscoverer.cs b/test/Microsoft.TestCommon/TheoryDiscoverer.cs index 8ca4c834e..cf62536fe 100644 --- a/test/Microsoft.TestCommon/TheoryDiscoverer.cs +++ b/test/Microsoft.TestCommon/TheoryDiscoverer.cs @@ -77,6 +77,7 @@ public override IEnumerable Discover( var testCase = new SkippedXunitTestCase( _diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), + TestMethodDisplayOptions.None, skipReason, baseCase.TestMethod, baseCase.TestMethodArguments); diff --git a/test/Microsoft.TestCommon/packages.config b/test/Microsoft.TestCommon/packages.config deleted file mode 100644 index 69a4ec438..000000000 --- a/test/Microsoft.TestCommon/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/test/Microsoft.TestCommon/xunit.runner.json b/test/Microsoft.TestCommon/xunit.runner.json index f9e0a66df..bbb2fc7f3 100644 --- a/test/Microsoft.TestCommon/xunit.runner.json +++ b/test/Microsoft.TestCommon/xunit.runner.json @@ -1,4 +1,4 @@ { - "appDomain": "denied", + "diagnosticMessages": false, "preEnumerateTheories": false } diff --git a/test/Microsoft.Web.Helpers.Test/LinkShareTest.cs b/test/Microsoft.Web.Helpers.Test/LinkShareTest.cs index 341a4fcb6..571da791b 100644 --- a/test/Microsoft.Web.Helpers.Test/LinkShareTest.cs +++ b/test/Microsoft.Web.Helpers.Test/LinkShareTest.cs @@ -29,7 +29,7 @@ public void RenderWithFacebookFirst_ReturnsHtmlWithFacebookAndThenOthersTest() string twitterTag = String.Empty; string actual; actual = LinkShare.GetHtml(pageTitle, pageLinkBack, twitterUserName, twitterTag, LinkShareSite.Facebook, LinkShareSite.All).ToString(); - Assert.True(actual.Contains("twitter.com")); + Assert.Contains("twitter.com", actual); int pos = actual.IndexOf("facebook.com"); Assert.True(pos > 0); int pos2 = actual.IndexOf("reddit.com"); diff --git a/test/Microsoft.Web.Helpers.Test/Microsoft.Web.Helpers.Test.csproj b/test/Microsoft.Web.Helpers.Test/Microsoft.Web.Helpers.Test.csproj index cdd4bc17c..1fdbb5fc0 100644 --- a/test/Microsoft.Web.Helpers.Test/Microsoft.Web.Helpers.Test.csproj +++ b/test/Microsoft.Web.Helpers.Test/Microsoft.Web.Helpers.Test.csproj @@ -1,6 +1,7 @@  - + + {2C653A66-8159-4A41-954F-A67915DFDA87} @@ -13,31 +14,31 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll - True + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True + - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -91,11 +92,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/Microsoft.Web.Helpers.Test/PreAppStartCodeTest.cs b/test/Microsoft.Web.Helpers.Test/PreAppStartCodeTest.cs index 8430ef072..6fb312633 100644 --- a/test/Microsoft.Web.Helpers.Test/PreAppStartCodeTest.cs +++ b/test/Microsoft.Web.Helpers.Test/PreAppStartCodeTest.cs @@ -1,7 +1,6 @@ // 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.Linq; using System.Web.WebPages.Razor; using System.Web.WebPages.TestUtils; using Microsoft.TestCommon; @@ -21,7 +20,7 @@ public void StartTest() // Assert var imports = WebPageRazorHost.GetGlobalImports(); - Assert.True(imports.Any(ns => ns.Equals("Microsoft.Web.Helpers"))); + Assert.Contains(imports, ns => ns.Equals("Microsoft.Web.Helpers")); }); } diff --git a/test/Microsoft.Web.Helpers.Test/ThemesTest.cs b/test/Microsoft.Web.Helpers.Test/ThemesTest.cs index d1a15cbae..9fe67e1ee 100644 --- a/test/Microsoft.Web.Helpers.Test/ThemesTest.cs +++ b/test/Microsoft.Web.Helpers.Test/ThemesTest.cs @@ -99,9 +99,9 @@ public void ThemesImplUsesScopeStorageToStoreProperties() themesImpl.Initialize(themeDirectory: themeDirectory, defaultTheme: defaultTheme); // Ensure Theme use scope storage to store properties - Assert.Equal(scope[ThemesImplementation.ThemesInitializedKey], true); - Assert.Equal(scope[ThemesImplementation.ThemeDirectoryKey], themeDirectory); - Assert.Equal(scope[ThemesImplementation.DefaultThemeKey], defaultTheme); + Assert.Equal((object)true, scope[ThemesImplementation.ThemesInitializedKey]); + Assert.Equal(themeDirectory, scope[ThemesImplementation.ThemeDirectoryKey]); + Assert.Equal(defaultTheme, scope[ThemesImplementation.DefaultThemeKey]); } [Fact] @@ -191,7 +191,7 @@ public void GetResourcePathReturnsItemFromThemeRootIfAvailable() var themePath = themesImpl.GetResourcePath(fileName: "wp7.css"); // Assert - Assert.Equal(themePath, @"themes/mobile/wp7.css"); + Assert.Equal(@"themes/mobile/wp7.css", themePath); } [Fact] @@ -207,7 +207,7 @@ public void GetResourcePathReturnsItemFromCurrentThemeDirectoryIfAvailable() var themePath = themesImpl.GetResourcePath(folder: "styles", fileName: "wp7.css"); // Assert - Assert.Equal(themePath, @"themes/mobile/styles/wp7.css"); + Assert.Equal(@"themes/mobile/styles/wp7.css", themePath); } [Fact] @@ -223,7 +223,7 @@ public void GetResourcePathReturnsItemFromDefaultThemeDirectoryIfNotFoundInCurre var themePath = themesImpl.GetResourcePath(folder: "styles", fileName: "main.css"); // Assert - Assert.Equal(themePath, @"themes/default/styles/main.css"); + Assert.Equal(@"themes/default/styles/main.css", themePath); } [Fact] @@ -270,9 +270,9 @@ public void AvaliableThemesReturnsTopLevelDirectoriesUnderThemeDirectory() // Assert Assert.Equal(3, themes.Count); - Assert.Equal(themes[0], "default"); - Assert.Equal(themes[1], "mobile"); - Assert.Equal(themes[2], "rotary-phone"); + Assert.Equal("default", themes[0]); + Assert.Equal("mobile", themes[1]); + Assert.Equal("rotary-phone", themes[2]); } /// diff --git a/test/Microsoft.Web.Helpers.Test/VideoTest.cs b/test/Microsoft.Web.Helpers.Test/VideoTest.cs index b5c87bc07..aacbe9a4d 100644 --- a/test/Microsoft.Web.Helpers.Test/VideoTest.cs +++ b/test/Microsoft.Web.Helpers.Test/VideoTest.cs @@ -24,13 +24,12 @@ public void FlashCannotOverrideHtmlAttributes() public void FlashDefaults() { string html = Video.Flash(GetContext(), _pathUtility, "http://foo.bar.com/foo.swf").ToString().Replace("\r\n", ""); - Assert.True(html.StartsWith( - "" - )); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.EndsWith("")); + Assert.StartsWith("", + html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.EndsWith("", html); } [Fact] @@ -52,39 +51,38 @@ public void FlashWithExposedOptions() play: false, loop: false, menu: false, backgroundColor: "#000", quality: "Q", scale: "S", windowMode: "WM", baseUrl: "http://foo.bar.com/", version: "1.0.0.0", htmlAttributes: new { id = "fl" }, embedName: "efl").ToString().Replace("\r\n", ""); - Assert.True(html.StartsWith( - "" - )); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); + "height=\"100px\" id=\"fl\" type=\"application/x-oleobject\" width=\"100px\" >", + html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); var embed = new Regex("").Match(html); Assert.True(embed.Success); - Assert.True(embed.Value.StartsWith("")); - Assert.True(html.Contains("")); + Assert.Contains("", html); + Assert.Contains("", html); // note - can't guarantee order of optional params: Assert.True( html.Contains("") || @@ -102,12 +100,10 @@ public void MediaPlayerCannotOverrideHtmlAttributes() public void MediaPlayerDefaults() { string html = Video.MediaPlayer(GetContext(), _pathUtility, "http://foo.bar.com/foo.wmv").ToString().Replace("\r\n", ""); - Assert.True(html.StartsWith( - "" - )); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.EndsWith("")); + Assert.StartsWith("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.EndsWith("", html); } [Fact] @@ -128,38 +124,36 @@ public void MediaPlayerWithExposedOptions() string html = Video.MediaPlayer(GetContext(), _pathUtility, "http://foo.bar.com/foo.wmv", width: "100px", height: "100px", autoStart: false, playCount: 2, uiMode: "UIMODE", stretchToFit: true, enableContextMenu: false, mute: true, volume: 1, baseUrl: "http://foo.bar.com/", htmlAttributes: new { id = "mp" }, embedName: "emp").ToString().Replace("\r\n", ""); - Assert.True(html.StartsWith( - "" - )); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); + Assert.StartsWith("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); var embed = new Regex("").Match(html); Assert.True(embed.Success); - Assert.True(embed.Value.StartsWith("")); - Assert.True(html.Contains("")); + Assert.Contains("", html); + Assert.Contains("", html); Assert.True( html.Contains("") || html.Contains("") @@ -180,16 +174,14 @@ public void SilverlightCannotOverrideHtmlAttributes() public void SilverlightDefaults() { string html = Video.Silverlight(GetContext(), _pathUtility, "http://foo.bar.com/foo.xap", "100px", "100px").ToString().Replace("\r\n", ""); - Assert.True(html.StartsWith( - "" - )); - Assert.True(html.Contains("")); - Assert.True(html.Contains( - "" + + Assert.StartsWith("", + html); + Assert.Contains("", html); + Assert.Contains("" + "\"Get")); - Assert.True(html.EndsWith("")); + "style=\"border-style:none\"/>", html); + Assert.EndsWith("", html); } [Fact] @@ -234,14 +226,13 @@ public void SilverlightWithExposedOptions() string html = Video.Silverlight(GetContext(), _pathUtility, "http://foo.bar.com/foo.xap", width: "85%", height: "85%", backgroundColor: "red", initParameters: "X=Y", minimumVersion: "1.0.0.0", autoUpgrade: false, htmlAttributes: new { id = "sl" }).ToString().Replace("\r\n", ""); - Assert.True(html.StartsWith( - "" - )); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); + Assert.StartsWith("", + html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); + Assert.Contains("", html); var embed = new Regex("").Match(html); Assert.False(embed.Success); @@ -252,8 +243,8 @@ public void SilverlightWithUnexposedOptions() { string html = Video.Silverlight(GetContext(), _pathUtility, "http://foo.bar.com/foo.xap", width: "50px", height: "50px", options: new { X = "Y", Z = 123 }).ToString().Replace("\r\n", ""); - Assert.True(html.Contains("")); - Assert.True(html.Contains("")); + Assert.Contains("", html); + Assert.Contains("", html); } [Fact] @@ -269,8 +260,8 @@ public void ValidatePathResolvesExistingLocalPath() HttpContextBase context = GetContext(serverMock.Object); string html = Video.Flash(context, pathUtility.Object, "foo.bar").ToString(); - Assert.True(html.StartsWith(" - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Web.Mvc.Test/Microsoft.Web.Mvc.Test.csproj b/test/Microsoft.Web.Mvc.Test/Microsoft.Web.Mvc.Test.csproj index 37bcdb8f0..23b4b28f3 100644 --- a/test/Microsoft.Web.Mvc.Test/Microsoft.Web.Mvc.Test.csproj +++ b/test/Microsoft.Web.Mvc.Test/Microsoft.Web.Mvc.Test.csproj @@ -1,6 +1,7 @@  - + + {6C28DA70-60F1-4442-967F-591BF3962EC5} @@ -15,36 +16,40 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -153,11 +158,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/Microsoft.Web.Mvc.Test/ModelBinding/Test/MutableObjectModelBinderTest.cs b/test/Microsoft.Web.Mvc.Test/ModelBinding/Test/MutableObjectModelBinderTest.cs index f6b007da4..3d030955f 100644 --- a/test/Microsoft.Web.Mvc.Test/ModelBinding/Test/MutableObjectModelBinderTest.cs +++ b/test/Microsoft.Web.Mvc.Test/ModelBinding/Test/MutableObjectModelBinderTest.cs @@ -591,10 +591,10 @@ public void SetProperty_SettingNullableTypeToNull_RequiredValidatorNotPresent_Pr // Assert Assert.False(bindingContext.ModelState.IsValid); - Assert.Equal(1, bindingContext.ModelState["foo.NameNoAttribute"].Errors.Count); + ModelError error = Assert.Single(bindingContext.ModelState["foo.NameNoAttribute"].Errors); Assert.Equal("This is a different exception." + Environment.NewLine + "Parameter name: value", - bindingContext.ModelState["foo.NameNoAttribute"].Errors[0].Exception.Message); + error.Exception.Message); } [Fact] @@ -622,8 +622,8 @@ public void SetProperty_SettingNullableTypeToNull_RequiredValidatorPresent_Prope // Assert Assert.False(bindingContext.ModelState.IsValid); - Assert.Equal(1, bindingContext.ModelState["foo.Name"].Errors.Count); - Assert.Equal("This message comes from the [Required] attribute.", bindingContext.ModelState["foo.Name"].Errors[0].ErrorMessage); + ModelError error = Assert.Single(bindingContext.ModelState["foo.Name"].Errors); + Assert.Equal("This message comes from the [Required] attribute.", error.ErrorMessage); } private static ModelMetadata GetMetadataForCanUpdateProperty(string propertyName) diff --git a/test/Microsoft.Web.Mvc.Test/Test/VersionTest.cs b/test/Microsoft.Web.Mvc.Test/Test/VersionTest.cs index 8120bd245..5235e0fee 100644 --- a/test/Microsoft.Web.Mvc.Test/Test/VersionTest.cs +++ b/test/Microsoft.Web.Mvc.Test/Test/VersionTest.cs @@ -13,7 +13,7 @@ public class VersionTest public void VerifyMVCVersionChangesAreIntentional() { Version mvcVersion = VersionTestHelper.GetVersionFromAssembly("System.Web.Mvc", typeof(Controller)); - Assert.Equal(new Version(5, 2, 4, 0), mvcVersion); + Assert.Equal(new Version(5, 3, 0, 0), mvcVersion); } } } diff --git a/test/Microsoft.Web.Mvc.Test/packages.config b/test/Microsoft.Web.Mvc.Test/packages.config index 2388b969c..72e333be0 100644 --- a/test/Microsoft.Web.Mvc.Test/packages.config +++ b/test/Microsoft.Web.Mvc.Test/packages.config @@ -1,12 +1,14 @@  - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.Web.WebPages.OAuth.Test/Microsoft.Web.WebPages.OAuth.Test.csproj b/test/Microsoft.Web.WebPages.OAuth.Test/Microsoft.Web.WebPages.OAuth.Test.csproj index c532e14f8..5985200ea 100644 --- a/test/Microsoft.Web.WebPages.OAuth.Test/Microsoft.Web.WebPages.OAuth.Test.csproj +++ b/test/Microsoft.Web.WebPages.OAuth.Test/Microsoft.Web.WebPages.OAuth.Test.csproj @@ -1,6 +1,7 @@  - + + {694C6EDF-EA52-438F-B745-82B025ECC0E7} @@ -13,8 +14,8 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True @@ -41,8 +42,8 @@ False ..\..\packages\DotNetOpenAuth.OpenId.RelyingParty.4.0.3.12153\lib\net40-full\DotNetOpenAuth.OpenId.RelyingParty.dll - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True @@ -50,19 +51,19 @@ - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -88,14 +89,20 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + - + <_VSRunnerVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">2.4.3 + <_VSRunnerVersion Condition=" '$(TargetFramework)' != 'netcoreapp2.1' ">2.4.5 + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + %(RecursiveDir)\%(Filename).cs + + + + + + + + diff --git a/test/System.Net.Http.Formatting.ns2_0.Test/System.Net.Http.Formatting.ns2_0.Test.csproj b/test/System.Net.Http.Formatting.ns2_0.Test/System.Net.Http.Formatting.ns2_0.Test.csproj new file mode 100644 index 000000000..8c7958b39 --- /dev/null +++ b/test/System.Net.Http.Formatting.ns2_0.Test/System.Net.Http.Formatting.ns2_0.Test.csproj @@ -0,0 +1,41 @@ + + + + net462;netcoreapp2.1;net6.0 + System.Net.Http + ..\..\bin\$(Configuration)\Test\ns2_0\ + $(Configurations);CodeAnalysis + false + $(DefineConstants);Testing_NetStandard2_0 + true + true + + + <_VSRunnerVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">2.4.3 + <_VSRunnerVersion Condition=" '$(TargetFramework)' != 'netcoreapp2.1' ">2.4.5 + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + %(RecursiveDir)\%(Filename).cs + + + + + + + + diff --git a/test/System.Web.Cors.Test/CorsEngineTest.cs b/test/System.Web.Cors.Test/CorsEngineTest.cs index e43f54208..f981c2ae6 100644 --- a/test/System.Web.Cors.Test/CorsEngineTest.cs +++ b/test/System.Web.Cors.Test/CorsEngineTest.cs @@ -395,7 +395,7 @@ public void EvaluatePolicy_PreflightRequest_ListedMethod_ReturnsSubsetOfListedMe CorsResult result = corsEngine.EvaluatePolicy(requestContext, policy); Assert.True(requestContext.IsPreflight); - Assert.Equal(1, result.AllowedMethods.Count()); + Assert.Single(result.AllowedMethods); Assert.Contains("PUT", result.AllowedMethods); } diff --git a/test/System.Web.Cors.Test/System.Web.Cors.Test.csproj b/test/System.Web.Cors.Test/System.Web.Cors.Test.csproj index 9907641eb..eea07163a 100644 --- a/test/System.Web.Cors.Test/System.Web.Cors.Test.csproj +++ b/test/System.Web.Cors.Test/System.Web.Cors.Test.csproj @@ -1,6 +1,7 @@  - + + Library @@ -13,30 +14,31 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True + - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -65,11 +67,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.Cors.Test/packages.config b/test/System.Web.Cors.Test/packages.config index 2388b969c..cafc6212c 100644 --- a/test/System.Web.Cors.Test/packages.config +++ b/test/System.Web.Cors.Test/packages.config @@ -1,12 +1,13 @@  - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/test/System.Web.Helpers.Test/ChartTest.cs b/test/System.Web.Helpers.Test/ChartTest.cs index e24740fbd..33943fb1a 100644 --- a/test/System.Web.Helpers.Test/ChartTest.cs +++ b/test/System.Web.Helpers.Test/ChartTest.cs @@ -26,8 +26,8 @@ public void BuildChartAddsDefaultArea() var chart = new Chart(GetContext(), GetVirtualPathProvider(), 100, 100); AssertBuiltChartAction(chart, c => { - Assert.Equal(1, c.ChartAreas.Count); - Assert.Equal("Default", c.ChartAreas[0].Name); + ChartArea chartArea = Assert.Single(c.ChartAreas); + Assert.Equal("Default", chartArea.Name); }); } @@ -38,10 +38,10 @@ public void XAxisOverrides() .SetXAxis("AxisX", 1, 100); AssertBuiltChartAction(chart, c => { - Assert.Equal(1, c.ChartAreas.Count); - Assert.Equal("AxisX", c.ChartAreas[0].AxisX.Title); - Assert.Equal(1, c.ChartAreas[0].AxisX.Minimum); - Assert.Equal(100, c.ChartAreas[0].AxisX.Maximum); + ChartArea chartArea = Assert.Single(c.ChartAreas); + Assert.Equal("AxisX", chartArea.AxisX.Title); + Assert.Equal(1, chartArea.AxisX.Minimum); + Assert.Equal(100, chartArea.AxisX.Maximum); }); } @@ -52,10 +52,10 @@ public void YAxisOverrides() .SetYAxis("AxisY", 1, 100); AssertBuiltChartAction(chart, c => { - Assert.Equal(1, c.ChartAreas.Count); - Assert.Equal("AxisY", c.ChartAreas[0].AxisY.Title); - Assert.Equal(1, c.ChartAreas[0].AxisY.Minimum); - Assert.Equal(100, c.ChartAreas[0].AxisY.Maximum); + ChartArea chartArea = Assert.Single(c.ChartAreas); + Assert.Equal("AxisY", chartArea.AxisY.Title); + Assert.Equal(1, chartArea.AxisY.Minimum); + Assert.Equal(100, chartArea.AxisY.Maximum); }); } @@ -71,7 +71,7 @@ public void ConstructorLoadsTemplate() public void ConstructorLoadsTheme() { //Vanilla theme - /* + /* * @@ -90,11 +90,11 @@ public void ConstructorLoadsTheme() var chart = new Chart(GetContext(), GetVirtualPathProvider(), 100, 100, theme: ChartTheme.Vanilla); AssertBuiltChartAction(chart, c => { - Assert.Equal(c.Palette, ChartColorPalette.SemiTransparent); + Assert.Equal(ChartColorPalette.SemiTransparent, c.Palette); Assert.Equal(c.BorderColor, Color.FromArgb(0, Color.Black)); - Assert.Equal(1, c.ChartAreas.Count); - Assert.False(c.ChartAreas[0].AxisX.MajorGrid.Enabled); - Assert.False(c.ChartAreas[0].AxisY.MinorGrid.Enabled); + ChartArea chartArea = Assert.Single(c.ChartAreas); + Assert.False(chartArea.AxisX.MajorGrid.Enabled); + Assert.False(chartArea.AxisY.MinorGrid.Enabled); }); } @@ -102,7 +102,7 @@ public void ConstructorLoadsTheme() public void ConstructorLoadsThemeAndTemplate() { //Vanilla theme - /* + /* * @@ -122,14 +122,14 @@ public void ConstructorLoadsThemeAndTemplate() var chart = new Chart(GetContext(), GetVirtualPathProvider(), 100, 100, theme: ChartTheme.Vanilla, themePath: template); AssertBuiltChartAction(chart, c => { - Assert.Equal(c.Palette, ChartColorPalette.SemiTransparent); + Assert.Equal(ChartColorPalette.SemiTransparent, c.Palette); Assert.Equal(c.BorderColor, Color.FromArgb(0, Color.Black)); - Assert.Equal(c.BorderlineDashStyle, ChartDashStyle.DashDot); - Assert.Equal(1, c.ChartAreas.Count); - Assert.Equal(c.Legends.Count, 1); - Assert.Equal(c.Legends[0].BackColor, Color.Red); - Assert.False(c.ChartAreas[0].AxisX.MajorGrid.Enabled); - Assert.False(c.ChartAreas[0].AxisY.MinorGrid.Enabled); + Assert.Equal(ChartDashStyle.DashDot, c.BorderlineDashStyle); + Legend legend = Assert.Single(c.Legends); + Assert.Equal(legend.BackColor, Color.Red); + ChartArea chartArea = Assert.Single(c.ChartAreas); + Assert.False(chartArea.AxisX.MajorGrid.Enabled); + Assert.False(chartArea.AxisY.MinorGrid.Enabled); }); } @@ -155,14 +155,14 @@ public void ConstructorLoadsThemeAndTemplate_VPPRegistrationChanging() // Assert AssertBuiltChartAction(chart, c => { - Assert.Equal(c.Palette, ChartColorPalette.SemiTransparent); + Assert.Equal(ChartColorPalette.SemiTransparent, c.Palette); Assert.Equal(c.BorderColor, Color.FromArgb(0, Color.Black)); - Assert.Equal(c.BorderlineDashStyle, ChartDashStyle.DashDot); - Assert.Equal(1, c.ChartAreas.Count); - Assert.Equal(c.Legends.Count, 1); - Assert.Equal(c.Legends[0].BackColor, Color.Red); - Assert.False(c.ChartAreas[0].AxisX.MajorGrid.Enabled); - Assert.False(c.ChartAreas[0].AxisY.MinorGrid.Enabled); + Assert.Equal(ChartDashStyle.DashDot, c.BorderlineDashStyle); + Legend legend = Assert.Single(c.Legends); + Assert.Equal(legend.BackColor, Color.Red); + ChartArea chartArea = Assert.Single(c.ChartAreas); + Assert.False(chartArea.AxisX.MajorGrid.Enabled); + Assert.False(chartArea.AxisY.MinorGrid.Enabled); }); Assert.Equal(1, provider1.FileExistsCalls); @@ -221,7 +221,7 @@ public void DataBindCrossTable() { Assert.Equal(2, c.Series.Count); Assert.Equal(2, c.Series[0].Points.Count); - Assert.Equal(1, c.Series[1].Points.Count); + Assert.Single(c.Series[1].Points); }); } @@ -281,8 +281,8 @@ public void DataBindTable() // todo - anything else to verify here? AssertBuiltChartAction(chart, c => { - Assert.Equal(1, c.Series.Count); - Assert.Equal(3, c.Series[0].Points.Count); + var series = Assert.Single(c.Series); + Assert.Equal(3, series.Points.Count); }); } @@ -300,8 +300,8 @@ public void DataBindTableWhenXFieldIsNull() // todo - anything else to verify here? AssertBuiltChartAction(chart, c => { - Assert.Equal(1, c.Series.Count); - Assert.Equal(3, c.Series[0].Points.Count); + var series = Assert.Single(c.Series); + Assert.Equal(3, series.Points.Count); }); } @@ -353,10 +353,10 @@ public void LegendDefaults() var chart = new Chart(GetContext(), GetVirtualPathProvider(), 100, 100).AddLegend(); AssertBuiltChartAction(chart, c => { - Assert.Equal(1, c.Legends.Count); + Legend legend = Assert.Single(c.Legends); // NOTE: Chart.Legends.Add will create default name - Assert.Equal("Legend1", c.Legends[0].Name); - Assert.Equal(1, c.Legends[0].BorderWidth); + Assert.Equal("Legend1", legend.Name); + Assert.Equal(1, legend.BorderWidth); }); } @@ -474,7 +474,7 @@ public void SaveXmlWritesToFile() chart.SaveXml(GetContext(), "SaveXmlWritesToFile.xml"); Assert.True(File.Exists("SaveXmlWritesToFile.xml")); string result = File.ReadAllText("SaveXmlWritesToFile.xml"); - Assert.True(result.Contains("BorderWidth=\"2\"")); + Assert.Contains("BorderWidth=\"2\"", result); } [Fact] @@ -531,8 +531,8 @@ public void SeriesOverrides() .AddSeries(chartType: "Bar"); AssertBuiltChartAction(chart, c => { - Assert.Equal(1, c.Series.Count); - Assert.Equal(SeriesChartType.Bar, c.Series[0].ChartType); + var series = Assert.Single(c.Series); + Assert.Equal(SeriesChartType.Bar, series.ChartType); }); } @@ -556,11 +556,11 @@ public void TitleDefaults() var chart = new Chart(GetContext(), GetVirtualPathProvider(), 100, 100).AddTitle(); AssertBuiltChartAction(chart, c => { - Assert.Equal(1, c.Titles.Count); + var title = Assert.Single(c.Titles); // NOTE: Chart.Titles.Add will create default name - Assert.Equal("Title1", c.Titles[0].Name); - Assert.Equal(String.Empty, c.Titles[0].Text); - Assert.Equal(1, c.Titles[0].BorderWidth); + Assert.Equal("Title1", title.Name); + Assert.Equal(String.Empty, title.Text); + Assert.Equal(1, title.BorderWidth); }); } diff --git a/test/System.Web.Helpers.Test/DynamicHelperTest.cs b/test/System.Web.Helpers.Test/DynamicHelperTest.cs index 5fcead088..15c2fb8e5 100644 --- a/test/System.Web.Helpers.Test/DynamicHelperTest.cs +++ b/test/System.Web.Helpers.Test/DynamicHelperTest.cs @@ -21,7 +21,7 @@ public void TryGetMemberValueReturnsValueIfBinderIsNotCSharp() bool result = DynamicHelper.TryGetMemberValue(dynamic, mockMemberBinder, out value); // Assert - Assert.Equal(value, "Bar"); + Assert.Equal("Bar", value); } private class MockMemberBinder : GetMemberBinder diff --git a/test/System.Web.Helpers.Test/ObjectInfoTest.cs b/test/System.Web.Helpers.Test/ObjectInfoTest.cs index 1635267df..ea38a4540 100644 --- a/test/System.Web.Helpers.Test/ObjectInfoTest.cs +++ b/test/System.Web.Helpers.Test/ObjectInfoTest.cs @@ -37,8 +37,8 @@ public void PrintWithNull() visitor.Print(null); // Assert - Assert.Equal(1, visitor.Values.Count); - Assert.Equal("null", visitor.Values[0]); + string value = Assert.Single(visitor.Values); + Assert.Equal("null", value); } [Fact] @@ -51,8 +51,8 @@ public void PrintWithEmptyString() visitor.Print(String.Empty); // Assert - Assert.Equal(1, visitor.Values.Count); - Assert.Equal(String.Empty, visitor.Values[0]); + string value = Assert.Single(visitor.Values); + Assert.Equal(String.Empty, value); } [Fact] @@ -65,8 +65,8 @@ public void PrintWithInt() visitor.Print(404); // Assert - Assert.Equal(1, visitor.Values.Count); - Assert.Equal("404", visitor.Values[0]); + string value = Assert.Single(visitor.Values); + Assert.Equal("404", value); } [Fact] @@ -99,7 +99,7 @@ public void PrintWithIEnumerable() // Assert foreach (var num in values) { - Assert.True(visitor.Values.Contains(num.ToString())); + Assert.Contains(num.ToString(), visitor.Values); } } @@ -116,8 +116,8 @@ public void PrintWithGenericIListPrintsIndex() // Assert for (int i = 0; i < values.Count; i++) { - Assert.True(visitor.Values.Contains(values[i].ToString())); - Assert.True(visitor.Indexes.Contains(i)); + Assert.Contains(values[i].ToString(), visitor.Values); + Assert.Contains(i, visitor.Indexes); } } @@ -134,8 +134,8 @@ public void PrintWithArrayPrintsIndex() // Assert for (int i = 0; i < values.Length; i++) { - Assert.True(visitor.Values.Contains(values[i].ToString())); - Assert.True(visitor.Indexes.Contains(i)); + Assert.Contains(values[i].ToString(), visitor.Values); + Assert.Contains(i, visitor.Indexes); } } @@ -148,7 +148,7 @@ public void PrintNameValueCollectionPrintsKeysAndValues() values["a"] = "1"; values["b"] = null; - // Act + // Act visitor.Print(values); // Assert @@ -165,7 +165,7 @@ public void PrintDateTime() MockObjectVisitor visitor = CreateObjectVisitor(); var dt = new DateTime(2001, 11, 20, 10, 30, 1); - // Act + // Act visitor.Print(dt); // Assert @@ -189,19 +189,19 @@ public void PrintCustomObjectPrintsMembers() using (new CultureReplacer("en-US")) { - // Act + // Act visitor.Print(person); // Assert Assert.Equal(9, visitor.Members.Count); - Assert.True(visitor.Members.Contains("double Age = 23.3")); - Assert.True(visitor.Members.Contains("string Name = David")); - Assert.True(visitor.Members.Contains("DateTime Dob = 11/19/1986 12:00:00 AM")); - Assert.True(visitor.Members.Contains("short Type = 1")); - Assert.True(visitor.Members.Contains("float Float = 0")); - Assert.True(visitor.Members.Contains("byte Byte = 0")); - Assert.True(visitor.Members.Contains("decimal Decimal = 0")); - Assert.True(visitor.Members.Contains("bool Bool = False")); + Assert.Contains("double Age = 23.3", visitor.Members); + Assert.Contains("string Name = David", visitor.Members); + Assert.Contains("DateTime Dob = 11/19/1986 12:00:00 AM", visitor.Members); + Assert.Contains("short Type = 1", visitor.Members); + Assert.Contains("float Float = 0", visitor.Members); + Assert.Contains("byte Byte = 0", visitor.Members); + Assert.Contains("decimal Decimal = 0", visitor.Members); + Assert.Contains("bool Bool = False", visitor.Members); } } @@ -223,10 +223,10 @@ public void PrintShowsVisitedWhenCircularReferenceInObjectGraph() // Act visitor.Print(node); - // Assert - Assert.True(visitor.Members.Contains("string Name = David")); - Assert.True(visitor.Members.Contains(String.Format("double Age = {0}", 23.3))); - Assert.True(visitor.Members.Contains("PersonNode Next = Visited")); + // Assert + Assert.Contains("string Name = David", visitor.Members); + Assert.Contains(String.Format("double Age = {0}", 23.3), visitor.Members); + Assert.Contains("PersonNode Next = Visited", visitor.Members); } [Fact] @@ -240,7 +240,7 @@ public void PrintShowsVisitedWhenCircularReferenceIsIEnumerable() // Act visitor.Print(values); - // Assert + // Assert Assert.Equal("Visited", visitor.Values[0]); Assert.Equal("Visited " + values.GetHashCode(), visitor.Visited[0]); } @@ -256,7 +256,7 @@ public void PrintShowsVisitedWhenCircularReferenceIsIDictionary() // Act visitor.Print(values); - // Assert + // Assert Assert.Equal("Visited", visitor.Values[0]); Assert.Equal("Visited " + values.GetHashCode(), visitor.Visited[0]); } @@ -275,9 +275,9 @@ public void PrintShowsVisitedWhenCircularReferenceIsNameValueCollection() // Act visitor.Print(values); - // Assert - Assert.True(visitor.Values.Contains("Visited")); - Assert.True(visitor.Visited.Contains("Visited " + nameValues.GetHashCode())); + // Assert + Assert.Contains("Visited", visitor.Values); + Assert.Contains("Visited " + nameValues.GetHashCode(), visitor.Visited); } [Fact] @@ -291,7 +291,7 @@ public void PrintExcludesWriteOnlyProperties() visitor.Print(cls); // Assert - Assert.Equal(0, visitor.Members.Count); + Assert.Empty(visitor.Members); } [Fact] @@ -309,14 +309,14 @@ public void PrintWritesEnumeratedElementsUntilLimitIsReached() { if (i < 1000) { - Assert.True(visitor.Values.Contains(i.ToString())); + Assert.Contains(i.ToString(), visitor.Values); } else { - Assert.False(visitor.Values.Contains(i.ToString())); + Assert.DoesNotContain(i.ToString(), visitor.Values); } } - Assert.True(visitor.Values.Contains("Limit Exceeded")); + Assert.Contains("Limit Exceeded", visitor.Values); } [Fact] @@ -330,8 +330,8 @@ public void PrintWithAnonymousType() visitor.Print(value); // Assert - Assert.True(visitor.Members.Contains("string Name = John")); - Assert.True(visitor.Members.Contains("int X = 1")); + Assert.Contains("string Name = John", visitor.Members); + Assert.Contains("int X = 1", visitor.Members); } [Fact] @@ -346,9 +346,9 @@ public void PrintClassWithPublicFields() // Actt visitor.Print(value); - // Assert - Assert.True(visitor.Members.Contains("string Foo = John")); - Assert.True(visitor.Members.Contains("int Bar = 1")); + // Assert + Assert.Contains("string Foo = John", visitor.Members); + Assert.Contains("int Bar = 1", visitor.Members); } [Fact] @@ -364,10 +364,10 @@ public void PrintClassWithDynamicMembersPrintsMembersIfGetDynamicMemberNamesIsIm // Act visitor.Print(d); - // Assert - Assert.True(visitor.Members.Contains("DynamicDictionary Cycle = Visited")); - Assert.True(visitor.Members.Contains("string Name = Foo")); - Assert.True(visitor.Members.Contains("Value = null")); + // Assert + Assert.Contains("DynamicDictionary Cycle = Visited", visitor.Members); + Assert.Contains("string Name = Foo", visitor.Members); + Assert.Contains("Value = null", visitor.Members); } [Fact] @@ -383,7 +383,7 @@ public void PrintClassWithDynamicMembersReturningNullPrintsNoMembers() // Act visitor.Print(d); - // Assert + // Assert Assert.False(visitor.Members.Any()); } @@ -425,7 +425,7 @@ public void PrintClassWithPropertyThatThrowsExceptionPrintsException() // Act visitor.Print(value); - // Assert + // Assert Assert.Equal("int MyProperty = Property accessor 'MyProperty' on object 'System.Web.Helpers.Test.ObjectInfoTest+ClassWithPropertyThatThrowsException' threw the following exception:'Property that shows an exception'", visitor.Members[0]); } @@ -457,7 +457,7 @@ public void PrintCharPrintsQuotedString() HtmlElement element = new HtmlElement("span"); printer.PushElement(element); - // Act + // Act printer.VisitConvertedValue('x', "x"); // Assert @@ -475,7 +475,7 @@ public void PrintEscapeCharPrintsEscapedCharAsLiteral() HtmlElement element = new HtmlElement("span"); printer.PushElement(element); - // Act + // Act printer.VisitConvertedValue('\t', "\t"); // Assert diff --git a/test/System.Web.Helpers.Test/PreComputedGridDataSourceTest.cs b/test/System.Web.Helpers.Test/PreComputedGridDataSourceTest.cs index fac1a4474..8ea02d796 100644 --- a/test/System.Web.Helpers.Test/PreComputedGridDataSourceTest.cs +++ b/test/System.Web.Helpers.Test/PreComputedGridDataSourceTest.cs @@ -27,13 +27,13 @@ public void PreSortedDataSourceReturnsAllRows() var grid = new WebGrid(GetContext()); var dataSource = new PreComputedGridDataSource(grid: grid, values: Enumerable.Range(0, 10).Cast(), totalRows: 10); - // Act + // Act var rows = dataSource.GetRows(new SortInfo { SortColumn = String.Empty }, 0); // Assert - Assert.Equal(rows.Count, 10); - Assert.Equal(rows.First().Value, 0); - Assert.Equal(rows.Last().Value, 9); + Assert.Equal(10, rows.Count); + Assert.Equal(0, rows.First().Value); + Assert.Equal(9, rows.Last().Value); } private HttpContextBase GetContext() diff --git a/test/System.Web.Helpers.Test/ServerInfoTest.cs b/test/System.Web.Helpers.Test/ServerInfoTest.cs index 178bbf2f7..e0a952436 100644 --- a/test/System.Web.Helpers.Test/ServerInfoTest.cs +++ b/test/System.Web.Helpers.Test/ServerInfoTest.cs @@ -111,7 +111,7 @@ public void ServerInfoProducesLegacyCasForNonHomogenousAppDomain() // Assert Assert.True(configValue.ContainsKey("Legacy Code Access Security")); - Assert.Equal(configValue["Legacy Code Access Security"], "Legacy Code Access Security has been detected on your system. Microsoft WebPage features require the ASP.NET 4 Code Access Security model. For information about how to resolve this, contact your server administrator."); + Assert.Equal("Legacy Code Access Security has been detected on your system. Microsoft WebPage features require the ASP.NET 4 Code Access Security model. For information about how to resolve this, contact your server administrator.", configValue["Legacy Code Access Security"]); }; AppDomainUtils.RunInSeparateAppDomain(GetAppDomainSetup(legacyCasEnabled: true), action); diff --git a/test/System.Web.Helpers.Test/System.Web.Helpers.Test.csproj b/test/System.Web.Helpers.Test/System.Web.Helpers.Test.csproj index 1c871f76e..1b14044ab 100644 --- a/test/System.Web.Helpers.Test/System.Web.Helpers.Test.csproj +++ b/test/System.Web.Helpers.Test/System.Web.Helpers.Test.csproj @@ -1,6 +1,7 @@  - + + {D3313BDF-8071-4AC8-9D98-ABF7F9E88A57} @@ -13,15 +14,16 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True + @@ -29,19 +31,19 @@ - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -91,11 +93,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.Helpers.Test/WebGridDataSourceTest.cs b/test/System.Web.Helpers.Test/WebGridDataSourceTest.cs index aba705461..5b7bdc88d 100644 --- a/test/System.Web.Helpers.Test/WebGridDataSourceTest.cs +++ b/test/System.Web.Helpers.Test/WebGridDataSourceTest.cs @@ -196,7 +196,7 @@ public void WebGridDataSourceReturnsPagedResultsIfRowsPerPageIsSpecified() var rows = dataSource.GetRows(new SortInfo(), 0); // Assert - Assert.Equal(rows.Count, 2); + Assert.Equal(2, rows.Count); Assert.Equal(rows.ElementAt(0).Value.LastName, "B2"); Assert.Equal(rows.ElementAt(1).Value.LastName, "A2"); } @@ -212,7 +212,7 @@ public void WebGridDataSourceReturnsPagedSortedResultsIfRowsPerPageAndSortAreSpe var rows = dataSource.GetRows(new SortInfo { SortColumn = "LastName", SortDirection = SortDirection.Descending }, 0); // Assert - Assert.Equal(rows.Count, 2); + Assert.Equal(2, rows.Count); Assert.Equal(rows.ElementAt(0).Value.LastName, "E2"); Assert.Equal(rows.ElementAt(1).Value.LastName, "D2"); } @@ -228,7 +228,7 @@ public void WebGridDataSourceReturnsFewerThanRowsPerPageIfNumberOfItemsIsInsuffi var rows = dataSource.GetRows(new SortInfo(), 1); // Assert - Assert.Equal(rows.Count, 2); + Assert.Equal(2, rows.Count); Assert.Equal(rows.ElementAt(0).Value.LastName, "C2"); Assert.Equal(rows.ElementAt(1).Value.LastName, "E2"); } @@ -244,7 +244,7 @@ public void WebGridDataSourceDoesNotThrowIfValuesAreNull() var rows = dataSource.GetRows(new SortInfo(), 0); // Assert - Assert.Equal(rows.Count, 2); + Assert.Equal(2, rows.Count); Assert.Equal(rows.ElementAt(0).Value, String.Empty); Assert.Null(rows.ElementAt(1).Value); } diff --git a/test/System.Web.Helpers.Test/WebGridTest.cs b/test/System.Web.Helpers.Test/WebGridTest.cs index 14c01ca46..2e2b23e1b 100644 --- a/test/System.Web.Helpers.Test/WebGridTest.cs +++ b/test/System.Web.Helpers.Test/WebGridTest.cs @@ -22,11 +22,11 @@ public void AjaxCheckedOnlyOnce() var grid = new WebGrid(GetContext(), ajaxUpdateContainerId: "grid") .Bind(new[] { new { First = "First", Second = "Second" } }); string html = grid.Table().ToString(); - Assert.True(html.Contains("" @@ -2172,9 +2172,9 @@ public void TableDoesNotThrowIfUnsortableColumnIsDefaultSortColumn() var html = grid.Table(); // Assert - Assert.Equal(grid.Rows[0]["Salary"], 5); - Assert.Equal(grid.Rows[1]["Salary"], 10); - Assert.Equal(grid.Rows[2]["Salary"], 15); + Assert.Equal(5, grid.Rows[0]["Salary"]); + Assert.Equal(10, grid.Rows[1]["Salary"]); + Assert.Equal(15, grid.Rows[2]["Salary"]); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" diff --git a/test/System.Web.Helpers.Test/WebImageTest.cs b/test/System.Web.Helpers.Test/WebImageTest.cs index e76fe58ce..ceb25c486 100644 --- a/test/System.Web.Helpers.Test/WebImageTest.cs +++ b/test/System.Web.Helpers.Test/WebImageTest.cs @@ -385,7 +385,7 @@ public void ResizePreservesFormat() image.Resize(200, 100, preserveAspectRatio: true, preventEnlarge: true); // Assert - Assert.Equal(image.ImageFormat, "png"); + Assert.Equal("png", image.ImageFormat); image.Save(GetContext(), saveAction, @"x:\1.png", null, false); using (Image modified = Image.FromStream(output)) @@ -980,7 +980,7 @@ public void SaveUsesOriginalFormatWhenNoFormatIsSpecified() image.Save(GetContext(), saveAction, filePath: specifiedOutputFile, imageFormat: null, forceWellKnownExtension: true); // Assert - Assert.Equal(Path.GetExtension(actualOutputFile), ".png"); + Assert.Equal(".png", Path.GetExtension(actualOutputFile)); } [Fact] @@ -997,7 +997,7 @@ public void SaveUsesOriginalFormatForStreamsWhenNoFormatIsSpecified() image.Save(GetContext(), saveAction, filePath: specifiedOutputFile, imageFormat: null, forceWellKnownExtension: true); // Assert - Assert.Equal(Path.GetExtension(actualOutputFile), ".png"); + Assert.Equal(".png", Path.GetExtension(actualOutputFile)); } [Fact] diff --git a/test/System.Web.Helpers.Test/WebMailTest.cs b/test/System.Web.Helpers.Test/WebMailTest.cs index a094521b0..f6dffcbb3 100644 --- a/test/System.Web.Helpers.Test/WebMailTest.cs +++ b/test/System.Web.Helpers.Test/WebMailTest.cs @@ -214,8 +214,8 @@ public void SetPropertiesOnMessageTest_SetsAllInfoCorrectlyOnMailMessageTest() Assert.Equal(Encoding.UTF8, message.BodyEncoding); Assert.Equal(Encoding.Unicode, message.HeadersEncoding); - Assert.True(message.Headers.AllKeys.Contains("header1")); - Assert.True(message.Attachments.Count == 1); + Assert.Contains("header1", message.Headers.AllKeys); + Assert.Single(message.Attachments); } finally { @@ -254,7 +254,7 @@ public void AssignHeaderValuesIgnoresMalformedHeaders() WebMail.AssignHeaderValues(message, headers); // Assert - Assert.Equal(1, message.Headers.Count); + Assert.Single(message.Headers); Assert.Equal("foo1", message.Headers.AllKeys[0]); Assert.Equal("bar1", message.Headers[0]); } @@ -318,7 +318,7 @@ public void AssignHeaderDoesNotThrowIfPriorityValueIsInvalid() Assert.Equal(MailPriority.Normal, message.Priority); // Assert we transparently set header values - Assert.Equal(1, message.Headers.Count); + Assert.Single(message.Headers); Assert.Equal("Priority", message.Headers.Keys[0]); Assert.Equal("invalid-value", message.Headers["Priority"]); } @@ -334,10 +334,10 @@ public void AssignHeaderDoesNotThrowIfMailAddressIsInvalid() WebMail.AssignHeaderValues(message, headers); // Assert - Assert.Equal(0, message.To.Count); + Assert.Empty(message.To); // Assert we transparently set header values - Assert.Equal(1, message.Headers.Count); + Assert.Single(message.Headers); Assert.Equal("To", message.Headers.Keys[0]); Assert.Equal("not-#-email@@", message.Headers["To"]); } @@ -353,10 +353,10 @@ public void AssignHeaderDoesNotThrowIfKnownHeaderValuesAreEmptyOrMalformed() WebMail.AssignHeaderValues(message, headers); // Assert - Assert.Equal(0, message.To.Count); + Assert.Empty(message.To); // Assert we transparently set header values - Assert.Equal(1, message.Headers.Count); + Assert.Single(message.Headers); Assert.Equal("Priority", message.Headers.Keys[0]); Assert.Equal("false", message.Headers["Priority"]); } diff --git a/test/System.Web.Helpers.Test/packages.config b/test/System.Web.Helpers.Test/packages.config index 2388b969c..cafc6212c 100644 --- a/test/System.Web.Helpers.Test/packages.config +++ b/test/System.Web.Helpers.Test/packages.config @@ -1,12 +1,13 @@  - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Cors.Test/AttributeBasedPolicyProviderFactoryTest.cs b/test/System.Web.Http.Cors.Test/AttributeBasedPolicyProviderFactoryTest.cs index 1ebf8c522..521f41c2c 100644 --- a/test/System.Web.Http.Cors.Test/AttributeBasedPolicyProviderFactoryTest.cs +++ b/test/System.Web.Http.Cors.Test/AttributeBasedPolicyProviderFactoryTest.cs @@ -5,7 +5,6 @@ using System.Net.Http; using System.Web.Cors; using System.Web.Http.Controllers; -using System.Web.Http.Hosting; using System.Web.Http.Routing; using Microsoft.TestCommon; using Moq; @@ -64,7 +63,7 @@ public void GetCorsPolicyProvider_Preflight_ReturnsCompleteControllerContext() request.SetRouteData(route.GetRouteData("/", request)); ICorsPolicyProvider provider = providerFactory.GetCorsPolicyProvider(request); - + // Assert Assert.NotNull(controllerContext); Assert.Equal(config, controllerContext.Configuration); @@ -86,7 +85,7 @@ public void GetCorsPolicyProvider_Preflight_DisposesControllerAfterActionSelecti HttpControllerContext controllerContext = null; var actionSelector = new Mock(); actionSelector.Setup(s => s.SelectAction(It.IsAny())) - .Callback(context => + .Callback(context => { Assert.False(((SampleController)context.Controller).Disposed); controllerContext = context; @@ -214,7 +213,7 @@ public void GetCorsPolicyProvider_ReturnsPolicyProvider_OnController() ICorsPolicyProvider policyProvider = providerFactory.GetCorsPolicyProvider(request); Assert.NotNull(policyProvider); - Assert.IsType(typeof(EnableCorsAttribute), policyProvider); + Assert.IsType(policyProvider); } [Fact] @@ -232,7 +231,7 @@ public void GetCorsPolicyProvider_ReturnsPolicyProvider_OnAction() ICorsPolicyProvider policyProvider = providerFactory.GetCorsPolicyProvider(request); Assert.NotNull(policyProvider); - Assert.IsType(typeof(DisableCorsAttribute), policyProvider); + Assert.IsType(policyProvider); } [Fact] @@ -250,8 +249,8 @@ public void GetCorsPolicyProvider_Preflight_ReturnsPolicyProviderUsingPerControl Assert.True(request.GetCorsRequestContext().IsPreflight); EnableCorsAttribute enableCorsAttribute = Assert.IsType(provider); - Assert.Equal(1, enableCorsAttribute.Origins.Count()); - Assert.Equal("http://example.com/", enableCorsAttribute.Origins.First()); + string origin = Assert.Single(enableCorsAttribute.Origins); + Assert.Equal("http://example.com/", origin); } [Fact] diff --git a/test/System.Web.Http.Cors.Test/Controllers/ThrowingController.cs b/test/System.Web.Http.Cors.Test/Controllers/ThrowingController.cs new file mode 100644 index 000000000..6879816c2 --- /dev/null +++ b/test/System.Web.Http.Cors.Test/Controllers/ThrowingController.cs @@ -0,0 +1,11 @@ +namespace System.Web.Http.Cors +{ + [EnableCors("*", "*", "*")] + public class ThrowingController : ApiController + { + public string Get() + { + throw new Exception(); + } + } +} diff --git a/test/System.Web.Http.Cors.Test/CorsHttpConfigurationExtensionsTest.cs b/test/System.Web.Http.Cors.Test/CorsHttpConfigurationExtensionsTest.cs index 160c87412..449702695 100644 --- a/test/System.Web.Http.Cors.Test/CorsHttpConfigurationExtensionsTest.cs +++ b/test/System.Web.Http.Cors.Test/CorsHttpConfigurationExtensionsTest.cs @@ -32,8 +32,8 @@ public void EnableCors_AddsCorsMessageHandler_DuringInitializerExecution() config.Initializer(config); - Assert.Equal(1, config.MessageHandlers.Count); - Assert.IsType(typeof(CorsMessageHandler), config.MessageHandlers[0]); + var handler = Assert.Single(config.MessageHandlers); + Assert.IsType(handler); } [Fact] @@ -49,8 +49,8 @@ public void EnableCors_IsIdempotent() config.Initializer(config); - Assert.Equal(1, config.MessageHandlers.Count); - Assert.IsType(typeof(CorsMessageHandler), config.MessageHandlers[0]); + var handler = Assert.Single(config.MessageHandlers); + Assert.IsType(handler); } [Fact] @@ -66,8 +66,8 @@ public void EnableCors_Initializer_IsIdempotent() config.Initializer(config); config.Initializer(config); - Assert.Equal(1, config.MessageHandlers.Count); - Assert.IsType(typeof(CorsMessageHandler), config.MessageHandlers[0]); + var handler = Assert.Single(config.MessageHandlers); + Assert.IsType(handler); } [Fact] @@ -96,7 +96,7 @@ public void EnableCors_AddsTracers_WhenTracingIsEnabled() config.Initializer(config); ICorsPolicyProviderFactory providerFactory = config.GetCorsPolicyProviderFactory(); - Assert.IsType(typeof(CorsPolicyProviderFactoryTracer), providerFactory); + Assert.IsType(providerFactory); } [Fact] @@ -116,7 +116,7 @@ public void GetCorsPolicyProviderFactory_ReturnsDefaultCorsPolicyProviderFactory ICorsPolicyProviderFactory providerFactory = config.GetCorsPolicyProviderFactory(); Assert.NotNull(providerFactory); - Assert.IsType(typeof(AttributeBasedPolicyProviderFactory), providerFactory); + Assert.IsType(providerFactory); } [Fact] @@ -145,7 +145,7 @@ public void GetCorsEngine_ReturnsDefaultCorsEngine() { HttpConfiguration config = new HttpConfiguration(); ICorsEngine corsEngine = config.GetCorsEngine(); - Assert.IsType(typeof(CorsEngine), corsEngine); + Assert.IsType(corsEngine); } [Fact] diff --git a/test/System.Web.Http.Cors.Test/CorsHttpResponseMessageExtensionsTest.cs b/test/System.Web.Http.Cors.Test/CorsHttpResponseMessageExtensionsTest.cs index 511066868..257ca5c54 100644 --- a/test/System.Web.Http.Cors.Test/CorsHttpResponseMessageExtensionsTest.cs +++ b/test/System.Web.Http.Cors.Test/CorsHttpResponseMessageExtensionsTest.cs @@ -48,7 +48,7 @@ public void WriteCorsHeaders_WritesAllowMethods() response.WriteCorsHeaders(corsResult); HttpResponseHeaders headers = response.Headers; - Assert.Equal(1, headers.Count()); + Assert.Single(headers); string[] allowMethods = headers.GetValues("Access-Control-Allow-Methods").FirstOrDefault().Split(','); Assert.Contains("DELETE", allowMethods); Assert.Contains("PUT", allowMethods); @@ -64,7 +64,7 @@ public void WriteCorsHeaders_WritesAllowExposedHeaders() response.WriteCorsHeaders(corsResult); HttpResponseHeaders headers = response.Headers; - Assert.Equal(1, headers.Count()); + Assert.Single(headers); string[] exposedHeaders = headers.GetValues("Access-Control-Expose-Headers").FirstOrDefault().Split(','); Assert.Contains("baz", exposedHeaders); } @@ -80,7 +80,7 @@ public void WriteCorsHeaders_WritesAllowHeaders() response.WriteCorsHeaders(corsResult); HttpResponseHeaders headers = response.Headers; - Assert.Equal(1, headers.Count()); + Assert.Single(headers); string[] allowHeaders = headers.GetValues("Access-Control-Allow-Headers").FirstOrDefault().Split(','); Assert.Contains("foo", allowHeaders); Assert.Contains("bar", allowHeaders); @@ -98,7 +98,7 @@ public void WriteCorsHeaders_WritesAllowCredentials() response.WriteCorsHeaders(corsResult); HttpResponseHeaders headers = response.Headers; - Assert.Equal(1, headers.Count()); + Assert.Single(headers); Assert.Equal("true", headers.GetValues("Access-Control-Allow-Credentials").FirstOrDefault()); } @@ -114,7 +114,7 @@ public void WriteCorsHeaders_WritesAllowOrigin() response.WriteCorsHeaders(corsResult); HttpResponseHeaders headers = response.Headers; - Assert.Equal(1, headers.Count()); + Assert.Single(headers); Assert.Equal("*", headers.GetValues("Access-Control-Allow-Origin").FirstOrDefault()); } @@ -130,7 +130,7 @@ public void WriteCorsHeaders_WritesPreflightMaxAge() response.WriteCorsHeaders(corsResult); HttpResponseHeaders headers = response.Headers; - Assert.Equal(1, headers.Count()); + Assert.Single(headers); Assert.Equal("10", headers.GetValues("Access-Control-Max-Age").FirstOrDefault()); } } diff --git a/test/System.Web.Http.Cors.Test/CorsMessageHandlerTest.cs b/test/System.Web.Http.Cors.Test/CorsMessageHandlerTest.cs index e3fe7cf49..c6ecfdf25 100644 --- a/test/System.Web.Http.Cors.Test/CorsMessageHandlerTest.cs +++ b/test/System.Web.Http.Cors.Test/CorsMessageHandlerTest.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using System.Web.Cors; +using System.Web.Http.ExceptionHandling; using System.Web.Http.Hosting; using Microsoft.TestCommon; @@ -180,6 +181,40 @@ public async Task SendAsync_HandlesExceptions_ThrownDuringPreflight() Assert.Equal(HttpStatusCode.MethodNotAllowed, response.StatusCode); } + [Fact] + public async Task SendAsync_Preflight_RethrowsExceptions_WhenRethrowFlagIsTrue() + { + HttpConfiguration config = new HttpConfiguration(); + config.Routes.MapHttpRoute("default", "{controller}"); + HttpServer server = new HttpServer(config); + CorsMessageHandler corsHandler = new CorsMessageHandler(config, true); + corsHandler.InnerHandler = server; + HttpMessageInvoker invoker = new HttpMessageInvoker(corsHandler); + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Options, "http://localhost/sample"); + request.SetConfiguration(config); + request.Headers.Add(CorsConstants.Origin, "http://localhost/"); + request.Headers.Add(CorsConstants.AccessControlRequestMethod, "RandomMethod"); + + await Assert.ThrowsAsync(() => invoker.SendAsync(request, CancellationToken.None)); + } + + [Fact] + public async Task SendAsync_RethrowsExceptions_WhenRethrowFlagIsTrue() + { + HttpConfiguration config = new HttpConfiguration(); + config.Routes.MapHttpRoute("default", "{controller}"); + config.Services.Replace(typeof(IExceptionHandler), new PassthroughExceptionHandler()); + HttpServer server = new HttpServer(config); + CorsMessageHandler corsHandler = new CorsMessageHandler(config, true); + corsHandler.InnerHandler = server; + HttpMessageInvoker invoker = new HttpMessageInvoker(corsHandler); + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/throwing"); + request.SetConfiguration(config); + request.Headers.Add(CorsConstants.Origin, "http://localhost/"); + + await Assert.ThrowsAsync(() => invoker.SendAsync(request, CancellationToken.None)); + } + [Fact] public Task HandleCorsRequestAsync_NullConfig_Throws() { @@ -238,5 +273,13 @@ public Task HandleCorsPreflightRequestAsync_NullContext_Throws() () => corsHandler.HandleCorsPreflightRequestAsync(new HttpRequestMessage(), null, CancellationToken.None), "corsRequestContext"); } + + private class PassthroughExceptionHandler : IExceptionHandler + { + public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken) + { + throw context.Exception; + } + } } } \ No newline at end of file diff --git a/test/System.Web.Http.Cors.Test/System.Web.Http.Cors.Test.csproj b/test/System.Web.Http.Cors.Test/System.Web.Http.Cors.Test.csproj index 37ffa33f1..b270959ce 100644 --- a/test/System.Web.Http.Cors.Test/System.Web.Http.Cors.Test.csproj +++ b/test/System.Web.Http.Cors.Test/System.Web.Http.Cors.Test.csproj @@ -1,6 +1,7 @@  - + + {1E89A3E9-0A7F-418F-B4BE-6E38A6315373} @@ -13,32 +14,36 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -76,6 +81,7 @@ + @@ -90,11 +96,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Cors.Test/Tracing/CorsPolicyProviderFactoryTracerTest.cs b/test/System.Web.Http.Cors.Test/Tracing/CorsPolicyProviderFactoryTracerTest.cs index 593d6143a..5f5a15bc9 100644 --- a/test/System.Web.Http.Cors.Test/Tracing/CorsPolicyProviderFactoryTracerTest.cs +++ b/test/System.Web.Http.Cors.Test/Tracing/CorsPolicyProviderFactoryTracerTest.cs @@ -44,7 +44,7 @@ public void GetCorsPolicyProvider_ReturnsCorsPolicyProviderTracer() ICorsPolicyProvider policyProvider = tracer.GetCorsPolicyProvider(new HttpRequestMessage()); - Assert.IsType(typeof(CorsPolicyProviderTracer), policyProvider); + Assert.IsType(policyProvider); } [Fact] diff --git a/test/System.Web.Http.Cors.Test/packages.config b/test/System.Web.Http.Cors.Test/packages.config index 2388b969c..72e333be0 100644 --- a/test/System.Web.Http.Cors.Test/packages.config +++ b/test/System.Web.Http.Cors.Test/packages.config @@ -1,12 +1,14 @@  - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Integration.Test/ApiExplorer/ParameterSourceTest.cs b/test/System.Web.Http.Integration.Test/ApiExplorer/ParameterSourceTest.cs index 60c3c0b34..d6bd4933f 100644 --- a/test/System.Web.Http.Integration.Test/ApiExplorer/ParameterSourceTest.cs +++ b/test/System.Web.Http.Integration.Test/ApiExplorer/ParameterSourceTest.cs @@ -69,8 +69,8 @@ public void EnumParameters_ShowUpCorrectlyOnDescription() ApiDescription description = explorer.ApiDescriptions.FirstOrDefault(desc => desc.ActionDescriptor.ActionName == "GetWithEnumParameter"); Assert.NotNull(description); - Assert.Equal(1, description.ParameterDescriptions.Count); - Assert.Equal(ApiParameterSource.FromUri, description.ParameterDescriptions[0].Source); + ApiParameterDescription parameterDescription = Assert.Single(description.ParameterDescriptions); + Assert.Equal(ApiParameterSource.FromUri, parameterDescription.Source); Assert.Equal("EnumParameterOverloads?scope={scope}", description.RelativePath); description = explorer.ApiDescriptions.FirstOrDefault(desc => desc.ActionDescriptor.ActionName == "GetWithTwoEnumParameters"); @@ -82,8 +82,8 @@ public void EnumParameters_ShowUpCorrectlyOnDescription() description = explorer.ApiDescriptions.FirstOrDefault(desc => desc.ActionDescriptor.ActionName == "GetWithNullableEnumParameter"); Assert.NotNull(description); - Assert.Equal(1, description.ParameterDescriptions.Count); - Assert.Equal(ApiParameterSource.FromUri, description.ParameterDescriptions[0].Source); + parameterDescription = Assert.Single(description.ParameterDescriptions); + Assert.Equal(ApiParameterSource.FromUri, parameterDescription.Source); Assert.Equal("EnumParameterOverloads?level={level}", description.RelativePath); } @@ -153,7 +153,7 @@ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceT public string Value { get; set; } } - // We only support complex types whose all of their individual + // We only support complex types whose all of their individual // properties can be converted from string. public class NonDescribable { diff --git a/test/System.Web.Http.Integration.Test/ApiExplorer/RoutesTest.cs b/test/System.Web.Http.Integration.Test/ApiExplorer/RoutesTest.cs index b21e5bb0d..2181f629f 100644 --- a/test/System.Web.Http.Integration.Test/ApiExplorer/RoutesTest.cs +++ b/test/System.Web.Http.Integration.Test/ApiExplorer/RoutesTest.cs @@ -20,7 +20,7 @@ public void VerifyDescription_OnEmptyRoute() IApiExplorer explorer = config.Services.GetApiExplorer(); Assert.NotNull(explorer); - Assert.Equal(0, explorer.ApiDescriptions.Count); + Assert.Empty(explorer.ApiDescriptions); } [Fact] @@ -31,7 +31,7 @@ public void VerifyDescription_OnInvalidRoute() IApiExplorer explorer = config.Services.GetApiExplorer(); Assert.NotNull(explorer); - Assert.Equal(0, explorer.ApiDescriptions.Count); + Assert.Empty(explorer.ApiDescriptions); } public static IEnumerable VerifyDescription_OnDefaultRoute_PropertyData diff --git a/test/System.Web.Http.Integration.Test/ContentNegotiation/CustomFormatterTests.cs b/test/System.Web.Http.Integration.Test/ContentNegotiation/CustomFormatterTests.cs index 155218057..f04d2f61a 100644 --- a/test/System.Web.Http.Integration.Test/ContentNegotiation/CustomFormatterTests.cs +++ b/test/System.Web.Http.Integration.Test/ContentNegotiation/CustomFormatterTests.cs @@ -45,10 +45,10 @@ public async Task CustomFormatter_Overrides_SetResponseHeaders_During_Conneg() IEnumerable versionHdr = null; Assert.True(response.Content.Headers.TryGetValues("Version", out versionHdr)); - Assert.Equal("1.3.5.0", versionHdr.First()); + Assert.Equal("1.3.5.0", versionHdr.First()); Assert.NotNull(response.Content); Assert.NotNull(response.Content.Headers.ContentType); - Assert.Equal("text/plainwithversioninfo", response.Content.Headers.ContentType.MediaType); + Assert.Equal("text/plainwithversioninfo", response.Content.Headers.ContentType.MediaType); } [Fact] @@ -66,8 +66,8 @@ public async Task CustomFormatter_Post_Returns_Request_String_Content() response.EnsureSuccessStatusCode(); Assert.NotNull(response.Content); Assert.NotNull(response.Content.Headers.ContentType); - Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType); - Assert.Equal("Hello World!", await response.Content.ReadAsStringAsync()); + Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType); + Assert.Equal("Hello World!", await response.Content.ReadAsStringAsync()); } [Fact] @@ -86,8 +86,8 @@ public async Task CustomFormatter_Post_Returns_Request_Integer_Content() response.EnsureSuccessStatusCode(); Assert.NotNull(response.Content); Assert.NotNull(response.Content.Headers.ContentType); - Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType); - Assert.Equal(100, Convert.ToInt32(await response.Content.ReadAsStringAsync())); + Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType); + Assert.Equal(100, Convert.ToInt32(await response.Content.ReadAsStringAsync())); } [Fact] @@ -106,7 +106,7 @@ public async Task CustomFormatter_Post_Returns_Request_ComplexType_Content() response.EnsureSuccessStatusCode(); Assert.NotNull(response.Content); Assert.NotNull(response.Content.Headers.ContentType); - Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType); + Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType); } private void SetupHost() diff --git a/test/System.Web.Http.Integration.Test/ContentNegotiation/HttpResponseReturnTests.cs b/test/System.Web.Http.Integration.Test/ContentNegotiation/HttpResponseReturnTests.cs index dcbf10c93..a2a36b385 100644 --- a/test/System.Web.Http.Integration.Test/ContentNegotiation/HttpResponseReturnTests.cs +++ b/test/System.Web.Http.Integration.Test/ContentNegotiation/HttpResponseReturnTests.cs @@ -41,8 +41,8 @@ public async Task ActionReturnsHttpResponseMessage(string action) Assert.NotNull(response.Content); Assert.NotNull(response.Content.Headers.ContentType); - Assert.Equal("application/xml", response.Content.Headers.ContentType.MediaType); - Assert.Equal(expectedResponseValue, await response.Content.ReadAsStringAsync()); + Assert.Equal("application/xml", response.Content.Headers.ContentType.MediaType); + Assert.Equal(expectedResponseValue, await response.Content.ReadAsStringAsync()); } [Theory] @@ -59,8 +59,8 @@ public async Task ActionReturnsHttpResponseMessageWithExplicitMediaType(string a Assert.NotNull(response.Content); Assert.NotNull(response.Content.Headers.ContentType); - Assert.Equal("application/xml", response.Content.Headers.ContentType.MediaType); - Assert.Equal(expectedResponseValue, await response.Content.ReadAsStringAsync()); + Assert.Equal("application/xml", response.Content.Headers.ContentType.MediaType); + Assert.Equal(expectedResponseValue, await response.Content.ReadAsStringAsync()); } [Theory] @@ -77,7 +77,7 @@ public async Task ReturnMultipleSetCookieHeadersShouldWork(string action) Assert.Equal(new[] { "cookie1", "cookie2" }, list); } - public void SetupHost() + private void SetupHost() { baseAddress = "http://localhost/"; diff --git a/test/System.Web.Http.Integration.Test/Controllers/ActionAttributesTest.cs b/test/System.Web.Http.Integration.Test/Controllers/ActionAttributesTest.cs index 2405a37fe..275c645f8 100644 --- a/test/System.Web.Http.Integration.Test/Controllers/ActionAttributesTest.cs +++ b/test/System.Web.Http.Integration.Test/Controllers/ActionAttributesTest.cs @@ -27,7 +27,7 @@ public void SelectAction_OnRouteWithActionParameter(string httpMethod, string re controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "test", typeof(ActionAttributeTestController)); HttpActionDescriptor descriptor = ApiControllerHelper.SelectAction(controllerContext); - Assert.Equal(expectedActionName, descriptor.ActionName); + Assert.Equal(expectedActionName, descriptor.ActionName); } [Theory] @@ -63,7 +63,7 @@ public void SelectAction_ThrowsMethodNotSupported_OnRouteWithActionParameter(str [InlineData("PUT", "ActionAttributeTest/AddUsers")] // id is required on this action, so url is invalid. 404 [InlineData("WHATEVER", "ActionAttributeTest/AddUsers")] // id is required on this action, so url is invalid. 404 [InlineData("GET", "ActionAttributeTest/Users")] // key param is required, bad url. 404 - [InlineData("POST", "ActionAttributeTest/Users")] // key param is required, bad url. 404 + [InlineData("POST", "ActionAttributeTest/Users")] // key param is required, bad url. 404 [InlineData("PATCHING", "ActionAttributeTest/Users")] // key param is required, bad url. 404 [InlineData("NonAction", "ActionAttributeTest/NonAction")] // NonAction, 404 [InlineData("GET", "ActionAttributeTest/NonAction")] // NonAction, 404 @@ -86,7 +86,7 @@ public void SelectAction_ThrowsNotFound_OnRouteWithActionParameter(string httpMe // Error message might be ApiControllerActionSelector_ActionNameNotFound or ApiControllerActionSelector_ActionNotFound string actualMessage = (string)((HttpError)content.Value)["MessageDetail"]; - Assert.True(actualMessage.StartsWith("No action was found on the controller 'ActionAttributeTestController' that matches")); + Assert.StartsWith("No action was found on the controller 'ActionAttributeTestController' that matches", actualMessage); } [Theory] @@ -115,7 +115,7 @@ public void SelectAction_OnDefaultRoute(string httpMethod, string requestUrl, st controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "test", typeof(ActionAttributeTestController)); HttpActionDescriptor descriptor = ApiControllerHelper.SelectAction(controllerContext); - Assert.Equal(expectedActionName, descriptor.ActionName); + Assert.Equal(expectedActionName, descriptor.ActionName); } [Theory] diff --git a/test/System.Web.Http.Integration.Test/Controllers/ApiControllerActionSelectorTest.cs b/test/System.Web.Http.Integration.Test/Controllers/ApiControllerActionSelectorTest.cs index af5ae0541..a359bc8f3 100644 --- a/test/System.Web.Http.Integration.Test/Controllers/ApiControllerActionSelectorTest.cs +++ b/test/System.Web.Http.Integration.Test/Controllers/ApiControllerActionSelectorTest.cs @@ -237,7 +237,7 @@ public void RequestToActionWith_HttpMethodDefinedByAttributeAndActionName() context.ControllerDescriptor = new HttpControllerDescriptor(context.Configuration, "test", typeof(TestController)); HttpActionDescriptor descriptor = ApiControllerHelper.SelectAction(context); - Assert.Equal("PutUser", descriptor.ActionName); + Assert.Equal("PutUser", descriptor.ActionName); // When you have the HttpMethod attribute, the convention should not be applied. httpMethod = "PUT"; @@ -254,7 +254,7 @@ public void RequestToActionWith_HttpMethodDefinedByAttributeAndActionName() AssertAllowedHeaders(exception.Response, HttpMethod.Get, new HttpMethod("PATCH"), HttpMethod.Post, HttpMethod.Delete, HttpMethod.Head); } - // Verify response has all the methods in its Allow header. values are unsorted. + // Verify response has all the methods in its Allow header. values are unsorted. private void AssertAllowedHeaders(HttpResponseMessage response, params HttpMethod[] allowedMethods) { foreach (var method in allowedMethods) diff --git a/test/System.Web.Http.Integration.Test/ExceptionHandling/HttpResponseExceptionTest.cs b/test/System.Web.Http.Integration.Test/ExceptionHandling/HttpResponseExceptionTest.cs index ee14a2278..1d9bac575 100644 --- a/test/System.Web.Http.Integration.Test/ExceptionHandling/HttpResponseExceptionTest.cs +++ b/test/System.Web.Http.Integration.Test/ExceptionHandling/HttpResponseExceptionTest.cs @@ -48,7 +48,7 @@ await ScenarioHelper.RunTestAsync( { Assert.NotNull(response.Content); Assert.NotNull(response.Content.Headers.ContentType); - Assert.Equal(response.Content.Headers.ContentType.MediaType, "application/json"); + Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType); if (throwAt == "DoNotThrow") { diff --git a/test/System.Web.Http.Integration.Test/ExceptionHandling/IncludeErrorDetailTest.cs b/test/System.Web.Http.Integration.Test/ExceptionHandling/IncludeErrorDetailTest.cs index 329d13025..85b9f66e4 100644 --- a/test/System.Web.Http.Integration.Test/ExceptionHandling/IncludeErrorDetailTest.cs +++ b/test/System.Web.Http.Integration.Test/ExceptionHandling/IncludeErrorDetailTest.cs @@ -97,7 +97,7 @@ private async Task AssertResponseDoesNotIncludeErrorDetailAsync(HttpResponseMess { Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); JObject json = JToken.Parse(await response.Content.ReadAsStringAsync()) as JObject; - Assert.Equal(1, json.Count); + Assert.Single(json); string errorMessage = ((JValue)json["Message"]).ToString(); Assert.Equal("An error has occurred.", errorMessage); } diff --git a/test/System.Web.Http.Integration.Test/ModelBinding/BodyBindingTests.cs b/test/System.Web.Http.Integration.Test/ModelBinding/BodyBindingTests.cs index c6332aade..5f45be66f 100644 --- a/test/System.Web.Http.Integration.Test/ModelBinding/BodyBindingTests.cs +++ b/test/System.Web.Http.Integration.Test/ModelBinding/BodyBindingTests.cs @@ -138,7 +138,7 @@ public async Task Body_Binds_ComplexType_Type_Key_Value_Read(string action, stri // Assert ModelBindOrder actualItem = await response.Content.ReadAsAsync(); - Assert.Equal(expectedItem, actualItem, new ModelBindOrderEqualityComparer()); + Assert.Equal(expectedItem, actualItem, new ModelBindOrderEqualityComparer()); } [Theory] @@ -168,7 +168,7 @@ public async Task Body_Binds_ComplexType_Type_Whole_Body_Read(string action, str // Assert ModelBindOrder actualItem = await response.Content.ReadAsAsync(); - Assert.Equal(expectedItem, actualItem, new ModelBindOrderEqualityComparer()); + Assert.Equal(expectedItem, actualItem, new ModelBindOrderEqualityComparer()); } } } diff --git a/test/System.Web.Http.Integration.Test/ModelBinding/CustomBindingTests.cs b/test/System.Web.Http.Integration.Test/ModelBinding/CustomBindingTests.cs index 7385df6b8..b509df14d 100644 --- a/test/System.Web.Http.Integration.Test/ModelBinding/CustomBindingTests.cs +++ b/test/System.Web.Http.Integration.Test/ModelBinding/CustomBindingTests.cs @@ -29,7 +29,7 @@ public async Task Custom_ValueProvider_Binds_Simple_Types_Get() // Assert string responseString = await response.Content.ReadAsStringAsync(); - Assert.Equal("5", responseString); + Assert.Equal("5", responseString); } } diff --git a/test/System.Web.Http.Integration.Test/ModelBinding/DefaultActionValueBinderTest.cs b/test/System.Web.Http.Integration.Test/ModelBinding/DefaultActionValueBinderTest.cs index 749fc5c60..a4c96b54d 100644 --- a/test/System.Web.Http.Integration.Test/ModelBinding/DefaultActionValueBinderTest.cs +++ b/test/System.Web.Http.Integration.Test/ModelBinding/DefaultActionValueBinderTest.cs @@ -63,7 +63,7 @@ public async Task BindValuesAsync_WithObjectContentInRequest_Works() // Assert var result = context.ActionArguments; - Assert.Equal(1, result.Count); + Assert.Single(result); var item = Assert.IsType(result["item"]); Assert.Equal(cust.FirstName, item.FirstName); Assert.Equal(cust.LastName, item.LastName); @@ -170,8 +170,8 @@ public async Task BindValuesAsync_Query_String_Values_To_Complex_Types() // Assert Assert.True(actionContext.ModelState.IsValid); - Assert.Equal(1, actionContext.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsType(actionContext.ActionArguments.First().Value); + KeyValuePair actionArgument = Assert.Single(actionContext.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsType(actionArgument.Value); Assert.Equal(5, deserializedActionValueItem.Id); Assert.Equal("queryFirstName", deserializedActionValueItem.FirstName); Assert.Equal("queryLastName", deserializedActionValueItem.LastName); @@ -197,8 +197,8 @@ public async Task BindValuesAsync_Query_String_Values_To_Post_Complex_Types() // Assert Assert.True(actionContext.ModelState.IsValid); - Assert.Equal(1, actionContext.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsType(actionContext.ActionArguments.First().Value); + KeyValuePair actionArgument = Assert.Single(actionContext.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsType(actionArgument.Value); Assert.Equal(5, deserializedActionValueItem.Id); Assert.Equal("queryFirstName", deserializedActionValueItem.FirstName); Assert.Equal("queryLastName", deserializedActionValueItem.LastName); @@ -224,8 +224,8 @@ public async Task BindValuesAsync_Query_String_Values_To_Post_Enumerable_Complex // Assert Assert.True(actionContext.ModelState.IsValid); - Assert.Equal(1, actionContext.ActionArguments.Count); - IEnumerable items = Assert.IsAssignableFrom>(actionContext.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(actionContext.ActionArguments); + IEnumerable items = Assert.IsAssignableFrom>(keyValuePair.Value); ActionValueItem deserializedActionValueItem = items.First(); Assert.Equal(5, deserializedActionValueItem.Id); Assert.Equal("queryFirstName", deserializedActionValueItem.FirstName); @@ -252,9 +252,9 @@ public async Task BindValuesAsync_Query_String_Values_To_Post_Enumerable_Complex // Assert Assert.True(actionContext.ModelState.IsValid); - Assert.Equal(1, actionContext.ActionArguments.Count); - IEnumerable items = Assert.IsAssignableFrom>(actionContext.ActionArguments.First().Value); - Assert.Equal(0, items.Count()); // expect unsuccessful bind but proves we don't loop infinitely + KeyValuePair keyValuePair = Assert.Single(actionContext.ActionArguments); + IEnumerable items = Assert.IsAssignableFrom>(keyValuePair.Value); + Assert.Empty(items); // expect unsuccessful bind but proves we don't loop infinitely } [Fact] @@ -276,8 +276,8 @@ public async Task BindValuesAsync_Query_String_Values_To_ComplexType_Using_Prefi await provider.BindValuesAsync(actionContext, cancellationToken); // Assert - Assert.Equal(1, actionContext.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsType(actionContext.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(actionContext.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsType(keyValuePair.Value); Assert.Equal(5, deserializedActionValueItem.Id); Assert.Equal("queryFirstName", deserializedActionValueItem.FirstName); Assert.Equal("queryLastName", deserializedActionValueItem.LastName); @@ -302,8 +302,8 @@ public async Task BindValuesAsync_Query_String_Values_To_ComplexType_Using_FromU await provider.BindValuesAsync(actionContext, cancellationToken); // Assert - Assert.Equal(1, actionContext.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsType(actionContext.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(actionContext.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsType(keyValuePair.Value); Assert.Equal(5, deserializedActionValueItem.Id); Assert.Equal("queryFirstName", deserializedActionValueItem.FirstName); Assert.Equal("queryLastName", deserializedActionValueItem.LastName); @@ -473,8 +473,8 @@ public async Task BindValuesAsync_RouteData_Values_To_Complex_Types() await provider.BindValuesAsync(controllerContext, cancellationToken); // Assert - Assert.Equal(1, controllerContext.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsType(controllerContext.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(controllerContext.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsType(keyValuePair.Value); Assert.Equal(6, deserializedActionValueItem.Id); Assert.Equal("routeFirstName", deserializedActionValueItem.FirstName); Assert.Equal("routeLastName", deserializedActionValueItem.LastName); @@ -504,8 +504,8 @@ public async Task BindValuesAsync_RouteData_Values_To_Complex_Types_Using_FromUr await provider.BindValuesAsync(controllerContext, cancellationToken); // Assert - Assert.Equal(1, controllerContext.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsType(controllerContext.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(controllerContext.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsType(keyValuePair.Value); Assert.Equal(6, deserializedActionValueItem.Id); Assert.Equal("routeFirstName", deserializedActionValueItem.FirstName); Assert.Equal("routeLastName", deserializedActionValueItem.LastName); @@ -532,8 +532,8 @@ public async Task BindValuesAsync_ControllerContext_CancellationToken() await provider.BindValuesAsync(actionContext, cancellationToken); // Assert - Assert.Equal(1, actionContext.ActionArguments.Count); - Assert.Equal(cancellationToken, actionContext.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(actionContext.ActionArguments); + Assert.Equal(cancellationToken, keyValuePair.Value); } #endregion ControllerContext @@ -558,8 +558,8 @@ public async Task BindValuesAsync_Body_To_Complex_Type_Json() await provider.BindValuesAsync(context, cancellationToken); // Assert - Assert.Equal(1, context.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(keyValuePair.Value); Assert.Equal(7, deserializedActionValueItem.Id); Assert.Equal("testFirstName", deserializedActionValueItem.FirstName); Assert.Equal("testLastName", deserializedActionValueItem.LastName); @@ -606,8 +606,8 @@ public async Task BindValuesAsync_Body_To_Complex_Type_FormUrlEncoded() await provider.BindValuesAsync(context, cancellationToken); // Assert - Assert.Equal(1, context.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(keyValuePair.Value); Assert.Equal(7, deserializedActionValueItem.Id); Assert.Equal("testFirstName", deserializedActionValueItem.FirstName); Assert.Equal("testLastName", deserializedActionValueItem.LastName); @@ -656,8 +656,8 @@ public async Task BindValuesAsync_Body_To_Complex_Type_Xml() await provider.BindValuesAsync(context, cancellationToken); // Assert - Assert.Equal(1, context.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(keyValuePair.Value); Assert.Equal(item.Id, deserializedActionValueItem.Id); Assert.Equal(item.FirstName, deserializedActionValueItem.FirstName); Assert.Equal(item.LastName, deserializedActionValueItem.LastName); @@ -692,8 +692,8 @@ public async Task BindValuesAsync_Body_To_Complex_Type_Xml_Structural() await provider.BindValuesAsync(context, cancellationToken); // Assert - Assert.Equal(1, context.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(keyValuePair.Value); Assert.Equal(7, deserializedActionValueItem.Id); Assert.Equal("testFirstName", deserializedActionValueItem.FirstName); Assert.Equal("testLastName", deserializedActionValueItem.LastName); @@ -738,8 +738,8 @@ public async Task BindValuesAsync_Body_To_Complex_Type_NullContent() await provider.BindValuesAsync(context, CancellationToken.None); // Assert - Assert.Equal(1, context.ActionArguments.Count); - object deserializedActionValueItem = context.ActionArguments.First().Value; + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + object deserializedActionValueItem = keyValuePair.Value; Assert.Null(deserializedActionValueItem); } @@ -795,8 +795,8 @@ public async Task BindValuesAsync_Body_To_Complex_Type_Using_FromBodyAttribute() await provider.BindValuesAsync(context, cancellationToken); // Assert - Assert.Equal(1, context.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(keyValuePair.Value); Assert.Equal(7, deserializedActionValueItem.Id); Assert.Equal("testFirstName", deserializedActionValueItem.FirstName); Assert.Equal("testLastName", deserializedActionValueItem.LastName); @@ -820,8 +820,8 @@ public async Task BindValuesAsync_Body_To_Complex_Type_Using_Formatter_To_Deseri await provider.BindValuesAsync(context, cancellationToken); // Assert - Assert.Equal(1, context.ActionArguments.Count); - ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + ActionValueItem deserializedActionValueItem = Assert.IsAssignableFrom(keyValuePair.Value); Assert.Equal(7, deserializedActionValueItem.Id); Assert.Equal("testFirstName", deserializedActionValueItem.FirstName); Assert.Equal("testLastName", deserializedActionValueItem.LastName); @@ -848,8 +848,8 @@ public async Task BindValuesAsync_Body_To_IEnumerable_Complex_Type_Json() await provider.BindValuesAsync(context, cancellationToken); // Assert - Assert.Equal(1, context.ActionArguments.Count); - IEnumerable items = Assert.IsAssignableFrom>(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + IEnumerable items = Assert.IsAssignableFrom>(keyValuePair.Value); ActionValueItem deserializedActionValueItem = items.First(); Assert.Equal(7, deserializedActionValueItem.Id); Assert.Equal("testFirstName", deserializedActionValueItem.FirstName); @@ -879,8 +879,8 @@ public async Task BindValuesAsync_Body_To_JToken() await provider.BindValuesAsync(context, cancellationToken); // Assert - Assert.Equal(1, context.ActionArguments.Count); - JToken deserializedJsonValue = Assert.IsAssignableFrom(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + JToken deserializedJsonValue = Assert.IsAssignableFrom(keyValuePair.Value); string deserializedJsonAsString = deserializedJsonValue.ToString(Formatting.None); Assert.Equal(json, deserializedJsonAsString); } @@ -983,8 +983,8 @@ public async Task BindValuesAsync_Config_BindParameter_ShouldNotBeAppliedToUnrel await provider.BindValuesAsync(context, CancellationToken.None); // Assert - Assert.Equal(1, context.ActionArguments.Count); - ActionValueItem result = Assert.IsAssignableFrom(context.ActionArguments.First().Value); + KeyValuePair keyValuePair = Assert.Single(context.ActionArguments); + ActionValueItem result = Assert.IsAssignableFrom(keyValuePair.Value); Assert.Equal(7, result.Id); Assert.Equal("testFirstName", result.FirstName); Assert.Equal("testLastName", result.LastName); diff --git a/test/System.Web.Http.Integration.Test/ModelBinding/ModelBindingController.cs b/test/System.Web.Http.Integration.Test/ModelBinding/ModelBindingController.cs index 783c9c94a..588803893 100644 --- a/test/System.Web.Http.Integration.Test/ModelBinding/ModelBindingController.cs +++ b/test/System.Web.Http.Integration.Test/ModelBinding/ModelBindingController.cs @@ -65,7 +65,6 @@ public int GetIntCustom([ValueProvider(typeof(RequestHeadersValueProviderFactory public Task GetIntAsync(int value, CancellationToken token) { - Assert.NotNull(token); TaskCompletionSource tcs = new TaskCompletionSource(); tcs.TrySetResult(value); return tcs.Task; @@ -236,8 +235,8 @@ public bool Equals(ModelBindOrder x, ModelBindOrder y) { Assert.True(x != null, "Expected ModelBindOrder cannot be null."); Assert.True(y != null, "Actual ModelBindOrder was null."); - Assert.Equal(x.ItemName, y.ItemName); - Assert.Equal(x.Quantity, y.Quantity); + Assert.Equal(x.ItemName, y.ItemName); + Assert.Equal(x.Quantity, y.Quantity); if (x.Customer != null) { diff --git a/test/System.Web.Http.Integration.Test/ModelBinding/QueryStringBindingTests.cs b/test/System.Web.Http.Integration.Test/ModelBinding/QueryStringBindingTests.cs index ffd0e1089..20ab3febf 100644 --- a/test/System.Web.Http.Integration.Test/ModelBinding/QueryStringBindingTests.cs +++ b/test/System.Web.Http.Integration.Test/ModelBinding/QueryStringBindingTests.cs @@ -40,7 +40,7 @@ public async Task Query_String_Binds_Simple_Types_Get(string action, string quer // Assert string responseString = await response.Content.ReadAsStringAsync(); - Assert.Equal(expectedResponse, responseString); + Assert.Equal(expectedResponse, responseString); } [Theory] @@ -65,7 +65,7 @@ public async Task Query_String_Binds_Simple_Types_Post(string action, string que // Assert string responseString = await response.Content.ReadAsStringAsync(); - Assert.Equal(expectedResponse, responseString); + Assert.Equal(expectedResponse, responseString); } [Theory] @@ -91,7 +91,7 @@ public async Task Query_String_ComplexType_Type_Get(string action, string queryS // Assert ModelBindOrder actualItem = await response.Content.ReadAsAsync(); - Assert.Equal(expectedItem, actualItem, new ModelBindOrderEqualityComparer()); + Assert.Equal(expectedItem, actualItem, new ModelBindOrderEqualityComparer()); } [Theory] @@ -116,7 +116,7 @@ public async Task Query_String_ComplexType_Type_Post(string action, string query // Assert ModelBindOrder actualItem = await response.Content.ReadAsAsync(); - Assert.Equal(expectedItem, actualItem, new ModelBindOrderEqualityComparer()); + Assert.Equal(expectedItem, actualItem, new ModelBindOrderEqualityComparer()); } [Theory] diff --git a/test/System.Web.Http.Integration.Test/ModelBinding/RouteBindingTests.cs b/test/System.Web.Http.Integration.Test/ModelBinding/RouteBindingTests.cs index f9f487840..d90d91e52 100644 --- a/test/System.Web.Http.Integration.Test/ModelBinding/RouteBindingTests.cs +++ b/test/System.Web.Http.Integration.Test/ModelBinding/RouteBindingTests.cs @@ -27,7 +27,7 @@ public async Task Route_Binds_Simple_Types_Get() // Assert string responseString = await response.Content.ReadAsStringAsync(); - Assert.Equal("\"ModelBinding:GetStringFromRoute\"", responseString); + Assert.Equal("\"ModelBinding:GetStringFromRoute\"", responseString); } } } \ No newline at end of file diff --git a/test/System.Web.Http.Integration.Test/System.Web.Http.Integration.Test.csproj b/test/System.Web.Http.Integration.Test/System.Web.Http.Integration.Test.csproj index a465a9b1a..6edd73613 100644 --- a/test/System.Web.Http.Integration.Test/System.Web.Http.Integration.Test.csproj +++ b/test/System.Web.Http.Integration.Test/System.Web.Http.Integration.Test.csproj @@ -1,6 +1,7 @@  - + + {3267DFC6-B34D-4011-BC0F-D3B56AF6F608} @@ -13,20 +14,21 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True - - False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + True + @@ -37,19 +39,19 @@ - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -147,11 +149,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Integration.Test/Tracing/TracingTest.cs b/test/System.Web.Http.Integration.Test/Tracing/TracingTest.cs index 39e6cffd9..bc5d1618b 100644 --- a/test/System.Web.Http.Integration.Test/Tracing/TracingTest.cs +++ b/test/System.Web.Http.Integration.Test/Tracing/TracingTest.cs @@ -380,12 +380,24 @@ private static IList UnexpectedTraces(IList expecte // artifact specific to testing in VS. (Attempting to load all types from xunit.runner.visualstudio.testadapter.dll // fails with recent xUnit.net packages. The assembly references Microsoft.VisualStudio.TestPlatform.ObjectModel.dll // which is not available with xUnit.net 2.0.x.) + // + // Similarly, ignore records for the same exception to allow test to succeed when using the xUnit MSBuild runner. + // In that case, missing types may come from System.Web and Microsoft.Build.Utilities.v4.0 as well as xunit.runner.msbuild.net452. if (actualRecord.Operation == null && actualRecord.Exception is ReflectionTypeLoadException && actualRecord.Message != null && - actualRecord.Message.StartsWith( - "Exception thrown while getting types from 'xunit.runner.visualstudio.testadapter, ", - StringComparison.Ordinal)) + (actualRecord.Message.StartsWith( + "Exception thrown while getting types from 'xunit.runner.visualstudio.testadapter, ", + StringComparison.Ordinal) || + actualRecord.Message.StartsWith( + "Exception thrown while getting types from 'xunit.runner.msbuild.", + StringComparison.Ordinal) || + actualRecord.Message.StartsWith( + "Exception thrown while getting types from 'System.Web, ", + StringComparison.Ordinal) || + actualRecord.Message.StartsWith( + "Exception thrown while getting types from 'Microsoft.Build.Utilities.", + StringComparison.Ordinal))) { continue; } @@ -397,8 +409,8 @@ actualRecord.Exception is ReflectionTypeLoadException && if (expectedTrace == null) { - unexpected.Add(string.Format("kind={0} category={1}, operator={2}, operation={3}", - actualRecord.Kind, actualRecord.Category, actualRecord.Operator, actualRecord.Operation)); + unexpected.Add(string.Format("kind={0} category={1}, operator={2}, operation={3}, message={4}", + actualRecord.Kind, actualRecord.Category, actualRecord.Operator, actualRecord.Operation, actualRecord.Message)); } } @@ -422,14 +434,26 @@ private static bool ConfirmTracingOrder(IList expectedRecor // artifact specific to testing in VS. (Attempting to load all types from xunit.runner.visualstudio.testadapter.dll // fails with recent xUnit.net packages. The assembly references Microsoft.VisualStudio.TestPlatform.ObjectModel.dll // which is not available with xUnit.net 2.0.x.) + // + // Similarly, ignore records for the same exception to allow test to succeed when using the xUnit MSBuild runner. + // In that case, missing types may come from System.Web and Microsoft.Build.Utilities.v4.0 as well as xunit.runner.msbuild.net452. var actualRecord = actualRecords.ElementAtOrDefault(traceBeginPos); - if (actualRecord != null && + while (actualRecord != null && actualRecord.Operation == null && actualRecord.Exception is ReflectionTypeLoadException && actualRecord.Message != null && - actualRecord.Message.StartsWith( - "Exception thrown while getting types from 'xunit.runner.visualstudio.testadapter, ", - StringComparison.Ordinal)) + (actualRecord.Message.StartsWith( + "Exception thrown while getting types from 'xunit.runner.visualstudio.testadapter, ", + StringComparison.Ordinal) || + actualRecord.Message.StartsWith( + "Exception thrown while getting types from 'xunit.runner.msbuild.", + StringComparison.Ordinal) || + actualRecord.Message.StartsWith( + "Exception thrown while getting types from 'System.Web, ", + StringComparison.Ordinal) || + actualRecord.Message.StartsWith( + "Exception thrown while getting types from 'Microsoft.Build.Utilities.", + StringComparison.Ordinal))) { traceBeginPos++; actualRecord = actualRecords.ElementAtOrDefault(traceBeginPos); diff --git a/test/System.Web.Http.Integration.Test/packages.config b/test/System.Web.Http.Integration.Test/packages.config index 2dc840259..72e333be0 100644 --- a/test/System.Web.Http.Integration.Test/packages.config +++ b/test/System.Web.Http.Integration.Test/packages.config @@ -1,13 +1,14 @@  - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Owin.Test/ExceptionHandling/DefaultExceptionHandlerTests.cs b/test/System.Web.Http.Owin.Test/ExceptionHandling/DefaultExceptionHandlerTests.cs index 90ad0b0d0..d8078d330 100644 --- a/test/System.Web.Http.Owin.Test/ExceptionHandling/DefaultExceptionHandlerTests.cs +++ b/test/System.Web.Http.Owin.Test/ExceptionHandling/DefaultExceptionHandlerTests.cs @@ -58,8 +58,7 @@ public async Task HandleAsync_HandlesExceptionViaCreateErrorResponse() // Assert IHttpActionResult result = context.Result; - Assert.IsType(typeof(ResponseMessageResult), result); - ResponseMessageResult typedResult = (ResponseMessageResult)result; + ResponseMessageResult typedResult = Assert.IsType(result); using (HttpResponseMessage response = typedResult.Response) { Assert.NotNull(response); @@ -78,14 +77,12 @@ public async Task HandleAsync_HandlesExceptionViaCreateErrorResponse() private static void AssertErrorResponse(HttpResponseMessage expected, HttpResponseMessage actual) { Assert.NotNull(expected); // Guard - Assert.IsType(typeof(ObjectContent), expected.Content); // Guard - ObjectContent expectedContent = (ObjectContent)expected.Content; + ObjectContent expectedContent = Assert.IsType>(expected.Content); // Guard Assert.NotNull(expectedContent.Formatter); // Guard Assert.NotNull(actual); Assert.Equal(expected.StatusCode, actual.StatusCode); - Assert.IsType(typeof(ObjectContent), actual.Content); - ObjectContent actualContent = (ObjectContent)actual.Content; + ObjectContent actualContent = Assert.IsType>(actual.Content); Assert.NotNull(actualContent.Formatter); Assert.Same(expectedContent.Formatter.GetType(), actualContent.Formatter.GetType()); Assert.Equal(expectedContent.Value, actualContent.Value); diff --git a/test/System.Web.Http.Owin.Test/HostAuthenticationAttributeTest.cs b/test/System.Web.Http.Owin.Test/HostAuthenticationAttributeTest.cs index f5253c4a2..404ef9bd2 100644 --- a/test/System.Web.Http.Owin.Test/HostAuthenticationAttributeTest.cs +++ b/test/System.Web.Http.Owin.Test/HostAuthenticationAttributeTest.cs @@ -135,8 +135,7 @@ public void InnerFilter_IsHostAuthenticationFilter_WhenUsingConstructorWithStrin IAuthenticationFilter innerFilter = product.InnerFilter; // Assert - Assert.IsType(innerFilter); - HostAuthenticationFilter typedInnerFilter = (HostAuthenticationFilter)innerFilter; + HostAuthenticationFilter typedInnerFilter = Assert.IsType(innerFilter); Assert.Same(expectedAuthenticationType, typedInnerFilter.AuthenticationType); } diff --git a/test/System.Web.Http.Owin.Test/HostAuthenticationFilterTest.cs b/test/System.Web.Http.Owin.Test/HostAuthenticationFilterTest.cs index fb8d87fc2..199835996 100644 --- a/test/System.Web.Http.Owin.Test/HostAuthenticationFilterTest.cs +++ b/test/System.Web.Http.Owin.Test/HostAuthenticationFilterTest.cs @@ -93,8 +93,7 @@ public async Task AuthenticateAsync_SetsClaimsPrincipal_WhenOwinAuthenticateRetu // Assert Assert.Null(context.ErrorResult); IPrincipal principal = context.Principal; - Assert.IsType(principal); - ClaimsPrincipal claimsPrincipal = (ClaimsPrincipal)principal; + ClaimsPrincipal claimsPrincipal = Assert.IsType(principal); IIdentity identity = claimsPrincipal.Identity; Assert.Same(expectedIdentity, identity); } @@ -291,8 +290,8 @@ public async Task ChallengeAsync_CreatesAuthenticationTypes_WhenOwinChallengeWit Assert.NotNull(challenge); string[] authenticationTypes = challenge.AuthenticationTypes; Assert.NotNull(authenticationTypes); - Assert.Equal(1, authenticationTypes.Length); - Assert.Same(expectedAuthenticationType, authenticationTypes[0]); + string authenticationType = Assert.Single(authenticationTypes); + Assert.Same(expectedAuthenticationType, authenticationType); AuthenticationProperties extra = challenge.Properties; Assert.Same(originalExtra, extra); } @@ -321,8 +320,8 @@ public async Task ChallengeAsync_CreatesOwinChallengeWithAuthenticationType_When Assert.NotNull(challenge); string[] authenticationTypes = challenge.AuthenticationTypes; Assert.NotNull(authenticationTypes); - Assert.Equal(1, authenticationTypes.Length); - Assert.Same(expectedAuthenticationType, authenticationTypes[0]); + string authenticationType = Assert.Single(authenticationTypes); + Assert.Same(expectedAuthenticationType, authenticationType); AuthenticationProperties extra = challenge.Properties; Assert.NotNull(extra); } diff --git a/test/System.Web.Http.Owin.Test/HttpMessageHandlerAdapterTest.cs b/test/System.Web.Http.Owin.Test/HttpMessageHandlerAdapterTest.cs index e196c155a..b8b25e30f 100644 --- a/test/System.Web.Http.Owin.Test/HttpMessageHandlerAdapterTest.cs +++ b/test/System.Web.Http.Owin.Test/HttpMessageHandlerAdapterTest.cs @@ -429,7 +429,6 @@ public async Task Invoke_BuildsUriWithHostAndPort() [InlineData(@"-_.~+""<>^`{|}")] // random unicode characters [InlineData("激光這")] - [InlineData("%24")] [InlineData("?#")] public async Task Invoke_CreatesUri_ThatGeneratesCorrectlyDecodedStrings(string decodedId) { @@ -447,6 +446,27 @@ public async Task Invoke_CreatesUri_ThatGeneratesCorrectlyDecodedStrings(string Assert.Equal(decodedId, routeData.Values["id"]); } + [Theory] + [InlineData("%24", "$")] + [InlineData("%28%29", "()")] + [InlineData("%5B%5D", "[]")] + [InlineData("%7B%7D", "{}")] + public async Task Invoke_CreatesUri_ContainingCorrectlyDecodedStrings(string encoded, string decoded) + { + var handler = CreateOKHandlerStub(); + var bufferPolicySelector = CreateBufferPolicySelector(bufferInput: false, bufferOutput: false); + var environment = CreateOwinEnvironment("GET", "http", "localhost", "/vroot", "/api/customers/" + encoded); + var options = CreateValidOptions(handler, bufferPolicySelector); + var adapter = CreateProductUnderTest(options); + var route = new HttpRoute("api/customers/{id}"); + + await adapter.Invoke(new OwinContext(environment)); + IHttpRouteData routeData = route.GetRouteData("/vroot", handler.Request); + + Assert.NotNull(routeData); + Assert.Equal(decoded, routeData.Values["id"]); + } + [Fact] public async Task Invoke_AddsRequestHeadersToRequestMessage() { @@ -630,8 +650,7 @@ public async Task Invoke_SetsOwinRequestContext() // Assert HttpRequestContext requestContext = request.GetRequestContext(); - Assert.IsType(requestContext); - OwinHttpRequestContext typedContext = (OwinHttpRequestContext)requestContext; + OwinHttpRequestContext typedContext = Assert.IsType(requestContext); Assert.Same(expectedContext, typedContext.Context); Assert.Same(request, typedContext.Request); } @@ -1171,7 +1190,7 @@ public async Task Invoke_IfExceptionHandlerSetsNullResult_PropogatesFaultedTaskE var exception = await Assert.ThrowsAsync(() => product.Invoke(context)); Assert.Same(expectedException, exception); Assert.NotNull(exception.StackTrace); - Assert.True(exception.StackTrace.StartsWith(expectedStackTrace)); + Assert.StartsWith(expectedStackTrace, exception.StackTrace); } } } diff --git a/test/System.Web.Http.Owin.Test/NonOwnedStreamTests.cs b/test/System.Web.Http.Owin.Test/NonOwnedStreamTests.cs index 4ccd45c82..c21948fb5 100644 --- a/test/System.Web.Http.Owin.Test/NonOwnedStreamTests.cs +++ b/test/System.Web.Http.Owin.Test/NonOwnedStreamTests.cs @@ -109,7 +109,7 @@ public void CanRead_IfDisposed_ReturnsFalse() bool canRead = product.CanRead; // Assert - Assert.Equal(false, canRead); + Assert.False(canRead); } } @@ -121,7 +121,7 @@ public void Dispose_DoesNotDisposeInnerStream() Mock mock = new Mock(MockBehavior.Strict); mock.Setup(s => s.Close()).Callback(() => innerStreamDisposed = true); mock.As().Setup(s => s.Dispose()); - mock.Protected().Setup("Dispose", true).Callback(() => innerStreamDisposed = true); + mock.Protected().Setup("Dispose", exactParameterMatch: true, args: true).Callback(() => innerStreamDisposed = true); using (Stream innerStream = mock.Object) using (Stream product = CreateProductUnderTest(innerStream)) @@ -159,7 +159,7 @@ public void Close_DoesNotDisposeInnerStream() Mock mock = new Mock(MockBehavior.Strict); mock.Setup(s => s.Close()).Callback(() => innerStreamDisposed = true); mock.As().Setup(s => s.Dispose()); - mock.Protected().Setup("Dispose", true).Callback(() => innerStreamDisposed = true); + mock.Protected().Setup("Dispose", exactParameterMatch: true, args: true).Callback(() => innerStreamDisposed = true); using (Stream innerStream = mock.Object) using (Stream product = CreateProductUnderTest(innerStream)) diff --git a/test/System.Web.Http.Owin.Test/OwinHostIntegrationTest.cs b/test/System.Web.Http.Owin.Test/OwinHostIntegrationTest.cs index b905d6576..1300d1fd5 100644 --- a/test/System.Web.Http.Owin.Test/OwinHostIntegrationTest.cs +++ b/test/System.Web.Http.Owin.Test/OwinHostIntegrationTest.cs @@ -12,6 +12,7 @@ namespace System.Web.Http.Owin { + [Xunit.Collection("PortReserver Collection")] // Avoid conflicts between different PortReserver consumers. public class OwinHostIntegrationTest { [Fact] @@ -75,7 +76,9 @@ private static string CreateUrl(PortReserver port, string localPath) return CreateBaseUrl(port) + "/" + localPath; } +#pragma warning disable xUnit1013 // Public method should be marked as test public void Configuration(IAppBuilder appBuilder) +#pragma warning restore xUnit1013 // Public method should be marked as test { var config = new HttpConfiguration(); config.Routes.MapHttpRoute("Default", "{controller}"); diff --git a/test/System.Web.Http.Owin.Test/OwinHttpRequestContextTests.cs b/test/System.Web.Http.Owin.Test/OwinHttpRequestContextTests.cs index 09758854b..ac40a660a 100644 --- a/test/System.Web.Http.Owin.Test/OwinHttpRequestContextTests.cs +++ b/test/System.Web.Http.Owin.Test/OwinHttpRequestContextTests.cs @@ -175,7 +175,7 @@ public void IncludeErrorDetailGet_ReturnsFalse_ByDefault() bool includeErrorDetail = context.IncludeErrorDetail; // Assert - Assert.Equal(false, includeErrorDetail); + Assert.False(includeErrorDetail); } } @@ -194,7 +194,7 @@ public void IncludeErrorDetailGet_ReturnsTrue_WhenUnconfiguredAndIsLocal() bool includeErrorDetail = context.IncludeErrorDetail; // Assert - Assert.Equal(true, includeErrorDetail); + Assert.True(includeErrorDetail); } } @@ -310,7 +310,7 @@ public void IsLocalGet_ReturnsFalse_ByDefault() bool isLocal = context.IsLocal; // Assert - Assert.Equal(false, isLocal); + Assert.False(isLocal); } } @@ -564,6 +564,30 @@ public void VirtualPathRootGet_ReturnsContextRequestPathBase() } } + // Regression test for #203. + [Fact] + public void VirtualPathRootGet_ReturnsUnescapedContextRequestPathBase() + { + // Arrange + var expectedVirtualPathRoot = "/a b"; + var owinRequestMock = new Mock(MockBehavior.Strict); + owinRequestMock + .Setup(r => r.PathBase) + .Returns(new PathString(expectedVirtualPathRoot)); + + var owinContext = CreateStubOwinContext(owinRequestMock.Object); + using (var request = CreateRequest()) + { + var context = CreateProductUnderTest(owinContext, request); + + // Act + var virtualPathRoot = context.VirtualPathRoot; + + // Assert + Assert.Equal(expectedVirtualPathRoot, virtualPathRoot); + } + } + [Theory] [InlineData(null)] [InlineData("")] diff --git a/test/System.Web.Http.Owin.Test/PassiveAuthenticationMessageHandlerTest.cs b/test/System.Web.Http.Owin.Test/PassiveAuthenticationMessageHandlerTest.cs index 690ca8d53..c33a0a466 100644 --- a/test/System.Web.Http.Owin.Test/PassiveAuthenticationMessageHandlerTest.cs +++ b/test/System.Web.Http.Owin.Test/PassiveAuthenticationMessageHandlerTest.cs @@ -104,11 +104,28 @@ public async Task SendAsync_Throws_WhenAuthenticationManagerIsNull() public async Task SendAsync_SetsRequestContextPrincipalToAnonymous_BeforeCallingInnerHandler() { // Arrange + var requestContextMock = new Mock(MockBehavior.Strict); + var sequence = new MockSequence(); + var initialPrincipal = new GenericPrincipal(new GenericIdentity("generic user"), new[] { "generic role" }); IPrincipal requestContextPrincipal = null; - Mock requestContextMock = new Mock(MockBehavior.Strict); requestContextMock + .InSequence(sequence) + .SetupGet(c => c.Principal) + .Returns(initialPrincipal); + requestContextMock + .InSequence(sequence) .SetupSet(c => c.Principal = It.IsAny()) - .Callback((value) => requestContextPrincipal = value); + .Callback(value => requestContextPrincipal = value); + + // SendAsync also restores the old principal. + requestContextMock + .InSequence(sequence) + .SetupGet(c => c.Principal) + .Returns(requestContextPrincipal); + requestContextMock + .InSequence(sequence) + .SetupSet(c => c.Principal = initialPrincipal); + IPrincipal principalBeforeInnerHandler = null; HttpMessageHandler inner = new LambdaHttpMessageHandler((ignore1, ignore2) => { @@ -116,20 +133,21 @@ public async Task SendAsync_SetsRequestContextPrincipalToAnonymous_BeforeCalling return Task.FromResult(null); }); HttpMessageHandler handler = CreateProductUnderTest(inner); - IOwinContext context = CreateOwinContext(); + var context = CreateOwinContext(); - using (HttpRequestMessage request = new HttpRequestMessage()) + using (var request = new HttpRequestMessage()) { request.SetOwinContext(context); request.SetRequestContext(requestContextMock.Object); // Act - HttpResponseMessage ignore = await handler.SendAsync(request, CancellationToken.None); + await handler.SendAsync(request, CancellationToken.None); } // Assert + Assert.Equal(requestContextPrincipal, principalBeforeInnerHandler); Assert.NotNull(principalBeforeInnerHandler); - IIdentity identity = principalBeforeInnerHandler.Identity; + var identity = principalBeforeInnerHandler.Identity; Assert.NotNull(identity); Assert.False(identity.IsAuthenticated); Assert.Null(identity.Name); @@ -156,8 +174,7 @@ public async Task SendAsync_SuppressesAuthenticationChallenges_WhenNoChallengeIs Assert.NotNull(challenge); string[] authenticationTypes = challenge.AuthenticationTypes; Assert.NotNull(authenticationTypes); - Assert.Equal(1, authenticationTypes.Length); - string authenticationType = authenticationTypes[0]; + string authenticationType = Assert.Single(authenticationTypes); Assert.Null(authenticationType); } @@ -185,8 +202,7 @@ public async Task SendAsync_SuppressesAuthenticationChallenges_WhenExistingAuthe Assert.NotNull(challenge); string[] authenticationTypes = challenge.AuthenticationTypes; Assert.NotNull(authenticationTypes); - Assert.Equal(1, authenticationTypes.Length); - string authenticationType = authenticationTypes[0]; + string authenticationType = Assert.Single(authenticationTypes); Assert.Null(authenticationType); AuthenticationProperties actualExtraWrapper = challenge.Properties; Assert.NotNull(actualExtraWrapper); @@ -217,8 +233,7 @@ public async Task SendAsync_SuppressesAuthenticationChallenges_WhenExistingAuthe Assert.NotNull(challenge); string[] authenticationTypes = challenge.AuthenticationTypes; Assert.NotNull(authenticationTypes); - Assert.Equal(1, authenticationTypes.Length); - string authenticationType = authenticationTypes[0]; + string authenticationType = Assert.Single(authenticationTypes); Assert.Null(authenticationType); AuthenticationProperties actualExtraWrapper = challenge.Properties; Assert.NotNull(actualExtraWrapper); diff --git a/test/System.Web.Http.Owin.Test/System.Web.Http.Owin.Test.csproj b/test/System.Web.Http.Owin.Test/System.Web.Http.Owin.Test.csproj index 99b60f332..7cf636838 100644 --- a/test/System.Web.Http.Owin.Test/System.Web.Http.Owin.Test.csproj +++ b/test/System.Web.Http.Owin.Test/System.Web.Http.Owin.Test.csproj @@ -1,6 +1,7 @@  - + + {C19267DD-3984-430C-AE18-4034F85DE4E5} @@ -13,49 +14,50 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - ..\..\packages\Microsoft.Owin.2.0.2\lib\net45\Microsoft.Owin.dll + ..\..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll - + False - ..\..\packages\Microsoft.Owin.Host.HttpListener.2.0.2\lib\net45\Microsoft.Owin.Host.HttpListener.dll + ..\..\packages\Microsoft.Owin.Host.HttpListener.4.2.2\lib\net45\Microsoft.Owin.Host.HttpListener.dll - + False - ..\..\packages\Microsoft.Owin.Hosting.2.0.2\lib\net45\Microsoft.Owin.Hosting.dll + ..\..\packages\Microsoft.Owin.Hosting.4.2.2\lib\net45\Microsoft.Owin.Hosting.dll - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True - - False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + True ..\..\packages\Owin.1.0\lib\net40\Owin.dll + - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -103,11 +105,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Owin.Test/packages.config b/test/System.Web.Http.Owin.Test/packages.config index 2e17a3165..f789b6961 100644 --- a/test/System.Web.Http.Owin.Test/packages.config +++ b/test/System.Web.Http.Owin.Test/packages.config @@ -1,17 +1,18 @@  - - - - - - - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/System.Web.Http.SelfHost.Test/Authentication/BasicOverHttpTest.cs b/test/System.Web.Http.SelfHost.Test/Authentication/BasicOverHttpTest.cs index 0b2a5739e..85cde9467 100644 --- a/test/System.Web.Http.SelfHost.Test/Authentication/BasicOverHttpTest.cs +++ b/test/System.Web.Http.SelfHost.Test/Authentication/BasicOverHttpTest.cs @@ -10,6 +10,7 @@ namespace System.Web.Http { + [Xunit.Collection("PortReserver Collection")] // Avoid conflicts between different PortReserver consumers. public class BasicOverHttpTest { [Fact] diff --git a/test/System.Web.Http.SelfHost.Test/DeeplyNestedTypeTests.cs b/test/System.Web.Http.SelfHost.Test/DeeplyNestedTypeTests.cs index c536aa005..5b0381caa 100644 --- a/test/System.Web.Http.SelfHost.Test/DeeplyNestedTypeTests.cs +++ b/test/System.Web.Http.SelfHost.Test/DeeplyNestedTypeTests.cs @@ -25,7 +25,7 @@ public DeepNestedTypeTests() this.SetupHost(); } - public void SetupHost() + private void SetupHost() { baseAddress = String.Format("http://localhost/"); diff --git a/test/System.Web.Http.SelfHost.Test/HttpSelfHostConfigurationTest.cs b/test/System.Web.Http.SelfHost.Test/HttpSelfHostConfigurationTest.cs index 096f5beda..8c6a68847 100644 --- a/test/System.Web.Http.SelfHost.Test/HttpSelfHostConfigurationTest.cs +++ b/test/System.Web.Http.SelfHost.Test/HttpSelfHostConfigurationTest.cs @@ -21,7 +21,7 @@ public static TheoryDataSet() { {"http://localhost/", HttpBindingSecurityMode.TransportCredentialOnly, HttpClientCredentialType.Basic}, - {"https://localhost/", HttpBindingSecurityMode.Transport, HttpClientCredentialType.Basic}, + {"https://localhost/", HttpBindingSecurityMode.Transport, HttpClientCredentialType.Basic}, }; } } @@ -33,7 +33,7 @@ public static TheoryDataSet() { {"http://localhost/", HttpBindingSecurityMode.TransportCredentialOnly, HttpClientCredentialType.Certificate}, - {"https://localhost/", HttpBindingSecurityMode.Transport, HttpClientCredentialType.Certificate}, + {"https://localhost/", HttpBindingSecurityMode.Transport, HttpClientCredentialType.Certificate}, }; } } @@ -49,7 +49,7 @@ public static TheoryDataSet - + + {7F29EE87-6A63-43C6-B7FF-74DD06815830} @@ -13,17 +14,17 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True - - False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + True @@ -36,19 +37,19 @@ - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -99,11 +100,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.Http.SelfHost.Test/packages.config b/test/System.Web.Http.SelfHost.Test/packages.config index 2dc840259..72e333be0 100644 --- a/test/System.Web.Http.SelfHost.Test/packages.config +++ b/test/System.Web.Http.SelfHost.Test/packages.config @@ -1,13 +1,14 @@  - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/test/System.Web.Http.SignalR.Test/System.Web.Http.SignalR.Test.csproj b/test/System.Web.Http.SignalR.Test/System.Web.Http.SignalR.Test.csproj index 61a555746..bea9c73c3 100644 --- a/test/System.Web.Http.SignalR.Test/System.Web.Http.SignalR.Test.csproj +++ b/test/System.Web.Http.SignalR.Test/System.Web.Http.SignalR.Test.csproj @@ -1,6 +1,7 @@  - + + {E22245AF-D5E1-46F6-B443-C886983EC50C} @@ -12,40 +13,41 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True ..\..\packages\Microsoft.AspNet.SignalR.Core.1.0.0\lib\net40\Microsoft.AspNet.SignalR.Core.dll - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True - - False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + True + - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -68,7 +70,6 @@ - @@ -79,11 +80,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.Http.SignalR.Test/app.config b/test/System.Web.Http.SignalR.Test/app.config deleted file mode 100644 index 44298137a..000000000 --- a/test/System.Web.Http.SignalR.Test/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/test/System.Web.Http.SignalR.Test/packages.config b/test/System.Web.Http.SignalR.Test/packages.config index 48f678845..76583074d 100644 --- a/test/System.Web.Http.SignalR.Test/packages.config +++ b/test/System.Web.Http.SignalR.Test/packages.config @@ -1,14 +1,15 @@  - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Test/Batch/BatchHttpRequestMessageExtensionsTest.cs b/test/System.Web.Http.Test/Batch/BatchHttpRequestMessageExtensionsTest.cs index d467fc1fd..26daa0fbe 100644 --- a/test/System.Web.Http.Test/Batch/BatchHttpRequestMessageExtensionsTest.cs +++ b/test/System.Web.Http.Test/Batch/BatchHttpRequestMessageExtensionsTest.cs @@ -48,8 +48,7 @@ public void CopyBatchRequestProperties_AddsBatchHttpRequestContext() // Assert HttpRequestContext context = subRequest.GetRequestContext(); - Assert.IsType(context); - BatchHttpRequestContext typedContext = (BatchHttpRequestContext)context; + BatchHttpRequestContext typedContext = Assert.IsType(context); Assert.Same(expectedOriginalContext, typedContext.BatchContext); } } diff --git a/test/System.Web.Http.Test/Batch/DefaultHttpBatchHandlerTest.cs b/test/System.Web.Http.Test/Batch/DefaultHttpBatchHandlerTest.cs index 5b3033684..d6283e1e9 100644 --- a/test/System.Web.Http.Test/Batch/DefaultHttpBatchHandlerTest.cs +++ b/test/System.Web.Http.Test/Batch/DefaultHttpBatchHandlerTest.cs @@ -281,6 +281,29 @@ public async Task ParseBatchRequestsAsync_Returns_RequestsFromMultipartContent() Assert.Equal("http://example.com/values", requests[1].RequestUri.AbsoluteUri); } + [Fact] + public async Task ParseBatchRequestsAsync_Returns_RequestsFromMultipartContent_WithUriSchemeSet_FromRequest() + { + DefaultHttpBatchHandler batchHandler = new DefaultHttpBatchHandler(new HttpServer()); + HttpRequestMessage request = new HttpRequestMessage + { + Content = new MultipartContent("mixed") + { + new HttpMessageContent(new HttpRequestMessage(HttpMethod.Get, "http://example.com/")), + new HttpMessageContent(new HttpRequestMessage(HttpMethod.Post, "https://example.com/values")) + }, + RequestUri = new Uri("https://example.com/") + }; + + IList requests = await batchHandler.ParseBatchRequestsAsync(request, CancellationToken.None); + + Assert.Equal(2, requests.Count); + Assert.Equal(HttpMethod.Get, requests[0].Method); + Assert.Equal("https://example.com/", requests[0].RequestUri.AbsoluteUri); + Assert.Equal(HttpMethod.Post, requests[1].Method); + Assert.Equal("https://example.com/values", requests[1].RequestUri.AbsoluteUri); + } + [Fact] public async Task ParseBatchRequestsAsync_CopiesPropertiesFromRequest_WithoutExcludedProperties() { diff --git a/test/System.Web.Http.Test/Batch/HttpBatchHandlerTest.cs b/test/System.Web.Http.Test/Batch/HttpBatchHandlerTest.cs index 073b4bd4a..2d907119a 100644 --- a/test/System.Web.Http.Test/Batch/HttpBatchHandlerTest.cs +++ b/test/System.Web.Http.Test/Batch/HttpBatchHandlerTest.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics.Contracts; -using System.Linq; using System.Net; using System.Net.Http; using System.Threading; @@ -82,12 +81,11 @@ public void ExceptionLoggerGet_IfUnset_ReturnsExceptionLoggerFromConfiguration() IExceptionLogger exceptionLogger = product.ExceptionLogger; // Assert - Assert.IsType(exceptionLogger); - CompositeExceptionLogger compositeLogger = (CompositeExceptionLogger)exceptionLogger; + CompositeExceptionLogger compositeLogger = Assert.IsType(exceptionLogger); IEnumerable loggers = compositeLogger.Loggers; Assert.NotNull(loggers); - Assert.Equal(1, loggers.Count()); - Assert.Same(expectedExceptionLogger, loggers.Single()); + IExceptionLogger logger = Assert.Single(loggers); + Assert.Same(expectedExceptionLogger, logger); } } } @@ -108,8 +106,7 @@ public void ExceptionHandlerGet_IfUnset_ReturnsExceptionHandlerFromConfiguration IExceptionHandler exceptionHandler = product.ExceptionHandler; // Assert - Assert.IsType(exceptionHandler); - LastChanceExceptionHandler lastChanceHandler = (LastChanceExceptionHandler)exceptionHandler; + LastChanceExceptionHandler lastChanceHandler = Assert.IsType(exceptionHandler); Assert.Same(expectedExceptionHandler, lastChanceHandler.InnerHandler); } } @@ -257,7 +254,7 @@ public async Task SendAsync_IfExceptionHandlerSetsNullResult_PropogatesFaultedTa // Assert Assert.Same(expectedException, exception); Assert.NotNull(exception.StackTrace); - Assert.True(exception.StackTrace.StartsWith(expectedStackTrace)); + Assert.StartsWith(expectedStackTrace, exception.StackTrace); } } diff --git a/test/System.Web.Http.Test/Controllers/ApiControllerTest.cs b/test/System.Web.Http.Test/Controllers/ApiControllerTest.cs index c20f481e2..1ab79101a 100644 --- a/test/System.Web.Http.Test/Controllers/ApiControllerTest.cs +++ b/test/System.Web.Http.Test/Controllers/ApiControllerTest.cs @@ -863,8 +863,7 @@ public void RequestSet_UpdatesRequestBackedContextRequest() using (HttpRequestMessage expectedRequest = CreateRequest()) { ApiController controller = CreateFakeController(); - Assert.IsType(controller.RequestContext); // Guard - RequestBackedHttpRequestContext context = (RequestBackedHttpRequestContext)controller.RequestContext; + RequestBackedHttpRequestContext context = Assert.IsType(controller.RequestContext); // Guard // Act controller.Request = expectedRequest; diff --git a/test/System.Web.Http.Test/Controllers/ExceptionFilterResultTests.cs b/test/System.Web.Http.Test/Controllers/ExceptionFilterResultTests.cs index 6d3ff0044..c57ffd90a 100644 --- a/test/System.Web.Http.Test/Controllers/ExceptionFilterResultTests.cs +++ b/test/System.Web.Http.Test/Controllers/ExceptionFilterResultTests.cs @@ -310,7 +310,7 @@ public async Task ExecuteAsync_IfFaultedTaskExceptionIsUnhandled_PreservesExcept Assert.NotNull(expectedStackTrace); Assert.NotNull(exception); Assert.NotNull(exception.StackTrace); - Assert.True(exception.StackTrace.StartsWith(expectedStackTrace)); + Assert.StartsWith(expectedStackTrace, exception.StackTrace); } } diff --git a/test/System.Web.Http.Test/Controllers/FilterGroupingTests.cs b/test/System.Web.Http.Test/Controllers/FilterGroupingTests.cs index 45937f9a9..a8d569d0b 100644 --- a/test/System.Web.Http.Test/Controllers/FilterGroupingTests.cs +++ b/test/System.Web.Http.Test/Controllers/FilterGroupingTests.cs @@ -22,10 +22,10 @@ public void ActionFilters_ReturnsEmptyArray_WhenFiltersIsEmpty() // Act IActionFilter[] actionFilters = product.ActionFilters; - + // Assert Assert.NotNull(actionFilters); - Assert.Equal(0, actionFilters.Length); + Assert.Empty(actionFilters); } [Fact] @@ -120,8 +120,8 @@ public void ActionFilters_ReturnsActionScopeActionFilters_WhenOverrideScopeIsAct // Assert Assert.NotNull(actionFilters); - Assert.Equal(1, actionFilters.Length); - Assert.Same(expectedActionFilter, actionFilters[0]); + IActionFilter singleFilter = Assert.Single(actionFilters); + Assert.Same(expectedActionFilter, singleFilter); } [Fact] @@ -169,8 +169,8 @@ public void AuthorizationFilters_ReturnsActionScopeAuthorizationFilters_WhenOver // Assert Assert.NotNull(authorizationFilters); - Assert.Equal(1, authorizationFilters.Length); - Assert.Same(expectedActionFilter, authorizationFilters[0]); + IAuthorizationFilter authorizationFilter = Assert.Single(authorizationFilters); + Assert.Same(expectedActionFilter, authorizationFilter); } [Fact] @@ -193,8 +193,8 @@ public void AuthenticationFilters_ReturnsActionScopeAuthenticationFilters_WhenOv // Assert Assert.NotNull(authenticationFilters); - Assert.Equal(1, authenticationFilters.Length); - Assert.Same(expectedActionFilter, authenticationFilters[0]); + IAuthenticationFilter authenticationFilter = Assert.Single(authenticationFilters); + Assert.Same(expectedActionFilter, authenticationFilter); } [Fact] @@ -216,8 +216,8 @@ public void ExceptionFilters_ReturnsActionScopeExceptionFilters_WhenOverrideScop // Assert Assert.NotNull(exceptionFilters); - Assert.Equal(1, exceptionFilters.Length); - Assert.Same(expectedActionFilter, exceptionFilters[0]); + IExceptionFilter exceptionFilter = Assert.Single(exceptionFilters); + Assert.Same(expectedActionFilter, exceptionFilter); } [Fact] @@ -237,10 +237,10 @@ public void FilterImplementingMultipleType_WhereOneTypeIsOverridden_AppearsOnlyI // Assert Assert.NotNull(actionFilters); - Assert.Equal(1, actionFilters.Length); - Assert.Same(expectedInstance, actionFilters[0]); + IActionFilter actionFilter = Assert.Single(actionFilters); + Assert.Same(expectedInstance, actionFilter); Assert.NotNull(exceptionFilters); - Assert.Equal(0, exceptionFilters.Length); + Assert.Empty(exceptionFilters); } private static IActionFilter CreateDummyActionFilter() diff --git a/test/System.Web.Http.Test/Controllers/HttpControllerDescriptorTest.cs b/test/System.Web.Http.Test/Controllers/HttpControllerDescriptorTest.cs index 360d6af6e..608b86448 100644 --- a/test/System.Web.Http.Test/Controllers/HttpControllerDescriptorTest.cs +++ b/test/System.Web.Http.Test/Controllers/HttpControllerDescriptorTest.cs @@ -123,7 +123,7 @@ public void GetFilters_InvokesGetCustomAttributesMethod() [Fact] public void Initialize_In_InheritenceHierarchy() { - // Verifies that initialization is run in order with , and that they all mutate on the same descriptor object + // Verifies that initialization is run in order with , and that they all mutate on the same descriptor object HttpConfiguration config = new HttpConfiguration(); // Act. @@ -139,7 +139,7 @@ public void Initialize_In_InheritenceHierarchy() [Fact] public void Initialize_In_InheritenceHierarchy_Branching() { - // Verifies that initialization is run in order with, and that they all mutate on the same descriptor object + // Verifies that initialization is run in order with, and that they all mutate on the same descriptor object HttpConfiguration config = new HttpConfiguration(); // Act. @@ -181,7 +181,7 @@ public void GetCustomAttributes_GetsInheritedAttributes() var attributes = desc.GetCustomAttributes(); - Assert.Equal(1, attributes.Count); + Assert.Single(attributes); } [Fact] @@ -192,7 +192,7 @@ public void GetCustomAttributesInheritTrue_GetsInheritedAttributes() var attributes = desc.GetCustomAttributes(inherit: true); - Assert.Equal(1, attributes.Count); + Assert.Single(attributes); } [Fact] @@ -214,7 +214,7 @@ public void GetCustomAttributesInheritFalse_GetsDeclaredAttributes() var attributes = desc.GetCustomAttributes(inherit: false); - Assert.Equal(1, attributes.Count); + Assert.Single(attributes); } class NoopControllerConfigAttribute : Attribute, IControllerConfiguration @@ -307,7 +307,7 @@ class MyDerived3Controller : MyDerived1Controller [Fact] public void Initialize_Append_A_Formatter() { - // Verifies that controller inherit the formatter list from the global config, and can mutate it. + // Verifies that controller inherit the formatter list from the global config, and can mutate it. HttpConfiguration config = new HttpConfiguration(); MediaTypeFormatter globalFormatter = new Mock().Object; @@ -328,8 +328,8 @@ class MyControllerWithCustomFormatterConfigAttribute : Attribute, IControllerCon { public void Initialize(HttpControllerSettings settings, HttpControllerDescriptor controllerDescriptor) { - // Appends to existing list. Formatter list has copy-on-write semantics. - Assert.Equal(1, settings.Formatters.Count); // the one we already set + // Appends to existing list. Formatter list has copy-on-write semantics. + Assert.Single(settings.Formatters); // the one we already set settings.Formatters.Add(MyControllerWithCustomFormatter.CustomFormatter); } } diff --git a/test/System.Web.Http.Test/Controllers/HttpParameterDescriptorTest.cs b/test/System.Web.Http.Test/Controllers/HttpParameterDescriptorTest.cs index 01bd10ea0..a37e33802 100644 --- a/test/System.Web.Http.Test/Controllers/HttpParameterDescriptorTest.cs +++ b/test/System.Web.Http.Test/Controllers/HttpParameterDescriptorTest.cs @@ -61,7 +61,7 @@ public void GetCustomAttributes_Returns_EmptyAttributes() HttpParameterDescriptor parameterDescriptor = new Mock { CallBase = true }.Object; IEnumerable attributes = parameterDescriptor.GetCustomAttributes(); - Assert.Equal(0, attributes.Count()); + Assert.Empty(attributes); } [Fact] @@ -70,7 +70,7 @@ public void GetCustomAttributes_AttributeType_Returns_EmptyAttributes() HttpParameterDescriptor parameterDescriptor = new Mock { CallBase = true }.Object; IEnumerable attributes = parameterDescriptor.GetCustomAttributes(); - Assert.Equal(0, attributes.Count()); + Assert.Empty(attributes); } } } diff --git a/test/System.Web.Http.Test/Controllers/ReflectedHttpActionDescriptorTest.cs b/test/System.Web.Http.Test/Controllers/ReflectedHttpActionDescriptorTest.cs index 73d64562b..4789bc463 100644 --- a/test/System.Web.Http.Test/Controllers/ReflectedHttpActionDescriptorTest.cs +++ b/test/System.Web.Http.Test/Controllers/ReflectedHttpActionDescriptorTest.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; using System.Net; using System.Net.Http; using System.Reflection; @@ -118,8 +117,8 @@ public void GetFilter_Returns_AttributedFilter() IEnumerable filters = actionDescriptor.GetFilters(); Assert.NotNull(filters); - Assert.Equal(1, filters.Count()); - Assert.Equal(typeof(AuthorizeAttribute), filters.First().GetType()); + IFilter filter = Assert.Single(filters); + Assert.IsType(filter); } [Fact] @@ -153,10 +152,10 @@ public void GetCustomAttributes_Returns_ActionAttributes() IEnumerable httpGet = actionDescriptor.GetCustomAttributes(); Assert.NotNull(filters); - Assert.Equal(1, filters.Count()); - Assert.Equal(typeof(AuthorizeAttribute), filters.First().GetType()); + IFilter filter = Assert.Single(filters); + Assert.IsType(filter); Assert.NotNull(httpGet); - Assert.Equal(1, httpGet.Count()); + Assert.Single(httpGet); } [Fact] @@ -168,8 +167,8 @@ public void GetParameters_Returns_ActionParameters() Collection parameterDescriptors = actionDescriptor.GetParameters(); Assert.Equal(2, parameterDescriptors.Count); - Assert.NotNull(parameterDescriptors.Where(p => p.ParameterName == "firstName").FirstOrDefault()); - Assert.NotNull(parameterDescriptors.Where(p => p.ParameterName == "lastName").FirstOrDefault()); + Assert.Contains(parameterDescriptors, p => p.ParameterName == "firstName"); + Assert.Contains(parameterDescriptors, p => p.ParameterName == "lastName"); } [Fact] diff --git a/test/System.Web.Http.Test/Controllers/ReflectedHttpParameterDescriptorTest.cs b/test/System.Web.Http.Test/Controllers/ReflectedHttpParameterDescriptorTest.cs index 2321bce54..4a7656342 100644 --- a/test/System.Web.Http.Test/Controllers/ReflectedHttpParameterDescriptorTest.cs +++ b/test/System.Web.Http.Test/Controllers/ReflectedHttpParameterDescriptorTest.cs @@ -88,8 +88,8 @@ public void GetCustomAttributes_Returns_ParameterAttributes() ReflectedHttpParameterDescriptor parameterDescriptor = new ReflectedHttpParameterDescriptor(actionDescriptor, parameterInfo); object[] attributes = parameterDescriptor.GetCustomAttributes().ToArray(); - Assert.Equal(1, attributes.Length); - Assert.Equal(typeof(FromBodyAttribute), attributes[0].GetType()); + object attribute = Assert.Single(attributes); + Assert.IsType(attribute); } [Fact] @@ -102,7 +102,7 @@ public void GetCustomAttributes_AttributeType_Returns_ParameterAttributes() ReflectedHttpParameterDescriptor parameterDescriptor = new ReflectedHttpParameterDescriptor(actionDescriptor, parameterInfo); IEnumerable attributes = parameterDescriptor.GetCustomAttributes(); - Assert.Equal(1, attributes.Count()); + Assert.Single(attributes); } } } diff --git a/test/System.Web.Http.Test/Controllers/RequestBackedHttpRequestContextTests.cs b/test/System.Web.Http.Test/Controllers/RequestBackedHttpRequestContextTests.cs index 8c01e5b5a..aa7f0a5fe 100644 --- a/test/System.Web.Http.Test/Controllers/RequestBackedHttpRequestContextTests.cs +++ b/test/System.Web.Http.Test/Controllers/RequestBackedHttpRequestContextTests.cs @@ -236,7 +236,7 @@ public void IncludeErrorDetailGet_ReturnsFalse_AsDefault() bool includeErrorDetail = context.IncludeErrorDetail; // Assert - Assert.Equal(false, includeErrorDetail); + Assert.False(includeErrorDetail); } [Theory] @@ -305,7 +305,7 @@ public void IsLocalGet_ReturnsFalse_AsDefault() bool isLocal = context.IsLocal; // Assert - Assert.Equal(false, isLocal); + Assert.False(isLocal); } [Theory] @@ -609,7 +609,7 @@ public void VirtualPathRootGet_ReturnsConfigurationVirtualPathRoot_WhenConfigura { // Arrange string expectedVirtualPathRoot = "/"; - + using (HttpConfiguration configuration = new HttpConfiguration(new HttpRouteCollection( expectedVirtualPathRoot))) { @@ -624,6 +624,28 @@ public void VirtualPathRootGet_ReturnsConfigurationVirtualPathRoot_WhenConfigura } } + [Theory] + [InlineData("a b")] + [InlineData("/a b")] + [InlineData("/a%20b")] + public void VirtualPathRootGet_ReturnsUnescapedConfigurationVirtualPathRoot(string configurationVirtualPathRoot) + { + // Arrange + var expectedVirtualPathRoot = "/a b"; + using (var routeCollection = new HttpRouteCollection(configurationVirtualPathRoot)) + using (var configuration = new HttpConfiguration(routeCollection)) + { + var context = CreateProductUnderTest(); + context.Configuration = configuration; + + // Act + var virtualPathRoot = context.VirtualPathRoot; + + // Assert + Assert.Equal(expectedVirtualPathRoot, virtualPathRoot); + } + } + [Fact] public void VirtualPathRootGet_IgnoresConfiguration_AfterVirtualPathRootSet() { diff --git a/test/System.Web.Http.Test/Controllers/VoidResultConverterTest.cs b/test/System.Web.Http.Test/Controllers/VoidResultConverterTest.cs index c05e5f29a..7622e931f 100644 --- a/test/System.Web.Http.Test/Controllers/VoidResultConverterTest.cs +++ b/test/System.Web.Http.Test/Controllers/VoidResultConverterTest.cs @@ -31,7 +31,8 @@ public void Convert_ReturnsResponseMessageWithRequestAssignedAndNoContentToRefle var result = _converter.Convert(_context, null); Assert.Equal(HttpStatusCode.NoContent, result.StatusCode); - Assert.Null(result.Content); + Assert.NotNull(result.Content); + Assert.Equal(0L, result.Content.Headers.ContentLength); Assert.Same(_request, result.RequestMessage); } } diff --git a/test/System.Web.Http.Test/Description/ApiParameterDescriptionTest.cs b/test/System.Web.Http.Test/Description/ApiParameterDescriptionTest.cs index ff706e053..5139241c2 100644 --- a/test/System.Web.Http.Test/Description/ApiParameterDescriptionTest.cs +++ b/test/System.Web.Http.Test/Description/ApiParameterDescriptionTest.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.Collections.Generic; -using System.Linq; using System.Reflection; using System.Web.Http.Controllers; using Microsoft.TestCommon; @@ -25,8 +24,8 @@ public void GetBindableProperties_WorksOnlyFor_PublicInstanceProperties_WithPubl IEnumerable bindableProperties = parameter.GetBindableProperties(); // Assert - Assert.Equal(1, bindableProperties.Count()); - Assert.Equal("ValidProperty", bindableProperties.Single().Name); + PropertyInfo bindableProperty = Assert.Single(bindableProperties); + Assert.Equal("ValidProperty", bindableProperty.Name); } } diff --git a/test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerActivatorTest.cs b/test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerActivatorTest.cs index 7db1b5780..191397e83 100644 --- a/test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerActivatorTest.cs +++ b/test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerActivatorTest.cs @@ -153,7 +153,7 @@ public void Create_ThrowsForNullDependencyScope() exception.Message); Assert.NotNull(exception.InnerException); Assert.Matches( - "A dependency resolver of type 'ObjectProxy(_\\d+)?' returned an invalid value of null from its " + + "A dependency resolver of type 'IDependencyResolverProxy' returned an invalid value of null from its " + "BeginScope method. If the container does not have a concept of scope, consider returning a scope " + "that resolves in the root of the container instead.", exception.InnerException.Message); diff --git a/test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerSelectorTest.cs b/test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerSelectorTest.cs index 259a9d7ba..805fa088a 100644 --- a/test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerSelectorTest.cs +++ b/test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerSelectorTest.cs @@ -125,7 +125,7 @@ public void SelectController_IsCaseInsensitive(string controllerTypeName) HttpControllerDescriptor descriptor = selector.SelectController(request); // Assert - Assert.IsType(typeof(HttpControllerDescriptor), descriptor); + Assert.IsType(descriptor); Assert.Equal(controllerType, descriptor.ControllerType); } diff --git a/test/System.Web.Http.Test/Dispatcher/HttpControllerDispatcherTest.cs b/test/System.Web.Http.Test/Dispatcher/HttpControllerDispatcherTest.cs index 678e3206e..1a47d2c5c 100644 --- a/test/System.Web.Http.Test/Dispatcher/HttpControllerDispatcherTest.cs +++ b/test/System.Web.Http.Test/Dispatcher/HttpControllerDispatcherTest.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics.Contracts; -using System.Linq; using System.Net; using System.Net.Http; using System.Runtime.ExceptionServices; @@ -81,12 +80,11 @@ public void ExceptionLoggerGet_IfUnset_ReturnsExceptionLoggerFromConfiguration() IExceptionLogger exceptionLogger = product.ExceptionLogger; // Assert - Assert.IsType(exceptionLogger); - CompositeExceptionLogger compositeLogger = (CompositeExceptionLogger)exceptionLogger; + CompositeExceptionLogger compositeLogger = Assert.IsType(exceptionLogger); IEnumerable loggers = compositeLogger.Loggers; Assert.NotNull(loggers); - Assert.Equal(1, loggers.Count()); - Assert.Same(expectedExceptionLogger, loggers.Single()); + IExceptionLogger logger = Assert.Single(loggers); + Assert.Same(expectedExceptionLogger, logger); } } } @@ -106,8 +104,7 @@ public void ExceptionHandlerGet_IfUnset_UsesExceptionHandlerFromConfiguration() IExceptionHandler exceptionHandler = product.ExceptionHandler; // Assert - Assert.IsType(exceptionHandler); - LastChanceExceptionHandler lastChanceHandler = (LastChanceExceptionHandler)exceptionHandler; + LastChanceExceptionHandler lastChanceHandler = Assert.IsType(exceptionHandler); Assert.Same(expectedExceptionHandler, lastChanceHandler.InnerHandler); } } @@ -359,7 +356,7 @@ public async Task SendAsync_IfExceptionHandlerSetsNullResult_PropogatesFaultedTa Assert.Same(exceptionInfo.SourceException, exception); Assert.NotNull(exception.StackTrace); - Assert.True(exception.StackTrace.StartsWith(expectedStackTrace)); + Assert.StartsWith(expectedStackTrace, exception.StackTrace); } } @@ -486,8 +483,7 @@ public async Task SendAsync_CreatesControllerContextWithRequestBackedRequestCont HttpResponseMessage ignore = await invoker.SendAsync(request, CancellationToken.None); // Assert - Assert.IsType(requestContext); - RequestBackedHttpRequestContext typedRequestContext = (RequestBackedHttpRequestContext)requestContext; + RequestBackedHttpRequestContext typedRequestContext = Assert.IsType(requestContext); Assert.Same(request, typedRequestContext.Request); Assert.Same(configuration, typedRequestContext.Configuration); } @@ -524,8 +520,7 @@ public async Task SendAsync_SetsRequestBackedRequestContextOnRequest_WhenRequest HttpResponseMessage ignore = await invoker.SendAsync(request, CancellationToken.None); // Assert - Assert.IsType(requestContext); - RequestBackedHttpRequestContext typedRequestContext = (RequestBackedHttpRequestContext)requestContext; + RequestBackedHttpRequestContext typedRequestContext = Assert.IsType(requestContext); Assert.Same(request, typedRequestContext.Request); Assert.Same(configuration, typedRequestContext.Configuration); } diff --git a/test/System.Web.Http.Test/Dispatcher/HttpRoutingDispatcherTest.cs b/test/System.Web.Http.Test/Dispatcher/HttpRoutingDispatcherTest.cs index 666d20fd7..653d577a8 100644 --- a/test/System.Web.Http.Test/Dispatcher/HttpRoutingDispatcherTest.cs +++ b/test/System.Web.Http.Test/Dispatcher/HttpRoutingDispatcherTest.cs @@ -171,7 +171,7 @@ public async Task SendAsync_IgnoreRoute_UsesRouteDataWithStopRoutingHandlerFromR HttpResponseMessage response = await invoker.SendAsync(expectedRequest, CancellationToken.None); // Assert - Assert.Equal(response.StatusCode, HttpStatusCode.NotFound); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); Assert.True(response.RequestMessage.Properties.ContainsKey(HttpPropertyKeys.NoRouteMatched)); } } diff --git a/test/System.Web.Http.Test/ExceptionHandling/CompositeExceptionLoggerTests.cs b/test/System.Web.Http.Test/ExceptionHandling/CompositeExceptionLoggerTests.cs index d29341786..9a70ebc34 100644 --- a/test/System.Web.Http.Test/ExceptionHandling/CompositeExceptionLoggerTests.cs +++ b/test/System.Web.Http.Test/ExceptionHandling/CompositeExceptionLoggerTests.cs @@ -35,8 +35,8 @@ public void Loggers_ContainsSpecifiedInstances() // Assert Assert.NotNull(loggers); - Assert.Equal(1, loggers.Count()); - Assert.Same(expectedLogger, loggers.Single()); + IExceptionLogger logger = Assert.Single(loggers); + Assert.Same(expectedLogger, logger); } @@ -54,8 +54,8 @@ public void Constructor_CapturesLoggersContents() expectedLoggers.Clear(); IEnumerable loggers = product.Loggers; Assert.NotNull(loggers); - Assert.Equal(1, loggers.Count()); - Assert.Same(expectedLogger, loggers.Single()); + IExceptionLogger logger = Assert.Single(loggers); + Assert.Same(expectedLogger, logger); } [Fact] diff --git a/test/System.Web.Http.Test/ExceptionHandling/DefaultExceptionHandlerTests.cs b/test/System.Web.Http.Test/ExceptionHandling/DefaultExceptionHandlerTests.cs index 67297862e..332ef879b 100644 --- a/test/System.Web.Http.Test/ExceptionHandling/DefaultExceptionHandlerTests.cs +++ b/test/System.Web.Http.Test/ExceptionHandling/DefaultExceptionHandlerTests.cs @@ -56,8 +56,7 @@ public async Task HandleAsync_HandlesExceptionViaCreateErrorResponse() // Assert IHttpActionResult result = context.Result; - Assert.IsType(typeof(ResponseMessageResult), result); - ResponseMessageResult typedResult = (ResponseMessageResult)result; + ResponseMessageResult typedResult = Assert.IsType(result); using (HttpResponseMessage response = typedResult.Response) { Assert.NotNull(response); @@ -95,14 +94,12 @@ public async Task HandleAsync_IfCatchBlockIsIExceptionFilter_LeavesExceptionUnha private static void AssertErrorResponse(HttpResponseMessage expected, HttpResponseMessage actual) { Assert.NotNull(expected); // Guard - Assert.IsType(typeof(ObjectContent), expected.Content); // Guard - ObjectContent expectedContent = (ObjectContent)expected.Content; + ObjectContent expectedContent = Assert.IsType>(expected.Content); // Guard Assert.NotNull(expectedContent.Formatter); // Guard Assert.NotNull(actual); Assert.Equal(expected.StatusCode, actual.StatusCode); - Assert.IsType(typeof(ObjectContent), actual.Content); - ObjectContent actualContent = (ObjectContent)actual.Content; + ObjectContent actualContent = Assert.IsType>(actual.Content); Assert.NotNull(actualContent.Formatter); Assert.Same(expectedContent.Formatter.GetType(), actualContent.Formatter.GetType()); Assert.Equal(expectedContent.Value, actualContent.Value); diff --git a/test/System.Web.Http.Test/ExceptionHandling/ExceptionLoggerTests.cs b/test/System.Web.Http.Test/ExceptionHandling/ExceptionLoggerTests.cs index 57f078a81..e202dad6a 100644 --- a/test/System.Web.Http.Test/ExceptionHandling/ExceptionLoggerTests.cs +++ b/test/System.Web.Http.Test/ExceptionHandling/ExceptionLoggerTests.cs @@ -141,7 +141,7 @@ public void ShouldLog_IfExceptionDataIsNull_ReturnsTrue() bool shouldLog = product.ShouldLog(context); // Assert - Assert.Equal(true, shouldLog); + Assert.True(shouldLog); } [Fact] @@ -169,7 +169,7 @@ public void ShouldLog_IfExceptionDataIsReadOnly_ReturnsTrue() bool shouldLog = product.ShouldLog(context); // Assert - Assert.Equal(true, shouldLog); + Assert.True(shouldLog); } [Fact] @@ -188,11 +188,11 @@ public void ShouldLog_IfExceptionDataIsEmpty_AddsLoggedByKeyWithLoggerValueAndRe bool shouldLog = product.ShouldLog(context); // Assert - Assert.Equal(true, shouldLog); + Assert.True(shouldLog); Assert.True(data.Contains(ExceptionLogger.LoggedByKey)); object loggedBy = data[ExceptionLogger.LoggedByKey]; - Assert.IsAssignableFrom>(loggedBy); - Assert.Contains(product, (ICollection)loggedBy); + ICollection loggedByCollection = Assert.IsAssignableFrom>(loggedBy); + Assert.Contains(product, loggedByCollection); } [Fact] @@ -213,7 +213,7 @@ public void ShouldLog_IfExceptionDataHasEmptyLoggedBy_AddsLoggerAndReturnsTrue() bool shouldLog = product.ShouldLog(context); // Assert - Assert.Equal(true, shouldLog); + Assert.True(shouldLog); Assert.True(data.Contains(ExceptionLogger.LoggedByKey)); object updatedLoggedBy = data[ExceptionLogger.LoggedByKey]; Assert.Same(loggedBy, updatedLoggedBy); @@ -238,7 +238,7 @@ public void ShouldLog_IfExceptionDataContainsLoggedByLogger_ReturnsFalse() bool shouldLog = product.ShouldLog(context); // Assert - Assert.Equal(false, shouldLog); + Assert.False(shouldLog); Assert.True(data.Contains(ExceptionLogger.LoggedByKey)); object updatedLoggedBy = data[ExceptionLogger.LoggedByKey]; Assert.Same(loggedBy, updatedLoggedBy); @@ -262,7 +262,7 @@ public void ShouldLog_IfExceptionDataContainsLoggedByOfIncompatibleType_ReturnsT bool shouldLog = product.ShouldLog(context); // Assert - Assert.Equal(true, shouldLog); + Assert.True(shouldLog); Assert.True(data.Contains(ExceptionLogger.LoggedByKey)); object updatedLoggedBy = data[ExceptionLogger.LoggedByKey]; Assert.Null(updatedLoggedBy); diff --git a/test/System.Web.Http.Test/ExceptionHandling/ExceptionServicesTests.cs b/test/System.Web.Http.Test/ExceptionHandling/ExceptionServicesTests.cs index 277567cf8..43d7e68d4 100644 --- a/test/System.Web.Http.Test/ExceptionHandling/ExceptionServicesTests.cs +++ b/test/System.Web.Http.Test/ExceptionHandling/ExceptionServicesTests.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.Collections.Generic; -using System.Linq; using System.Web.Http.Controllers; using Microsoft.TestCommon; using Moq; @@ -24,10 +23,9 @@ public void GetLoggerWithServices_ReturnsCompositeExceptionLoggerWithServicesLog IExceptionLogger logger = ExceptionServices.GetLogger(services); // Assert - Assert.IsType(logger); - IEnumerable loggers = ((CompositeExceptionLogger)logger).Loggers; - Assert.Equal(1, loggers.Count()); - Assert.Same(expectedLogger, loggers.Single()); + IEnumerable loggers = Assert.IsType(logger).Loggers; + IExceptionLogger actualLogger = Assert.Single(loggers); + Assert.Same(expectedLogger, actualLogger); } } @@ -71,10 +69,9 @@ public void GetLoggerWithConfiguration_ReturnsCompositeExceptionLoggerWithServic IExceptionLogger logger = ExceptionServices.GetLogger(configuration); // Assert - Assert.IsType(logger); - IEnumerable loggers = ((CompositeExceptionLogger)logger).Loggers; - Assert.Equal(1, loggers.Count()); - Assert.Same(expectedLogger, loggers.Single()); + IEnumerable loggers = Assert.IsType(logger).Loggers; + IExceptionLogger actualLogger = Assert.Single(loggers); + Assert.Same(expectedLogger, actualLogger); } } @@ -100,8 +97,7 @@ public void GetHandlerWithServices_ReturnsLastChanceHandlerWithServicesInnerHand IExceptionHandler handler = ExceptionServices.GetHandler(services); // Assert - Assert.IsType(handler); - IExceptionHandler innerHandler = ((LastChanceExceptionHandler)handler).InnerHandler; + IExceptionHandler innerHandler = Assert.IsType(handler).InnerHandler; Assert.Same(expectedHandler, innerHandler); } } @@ -136,8 +132,7 @@ public void GetHandlerWithServices_IfHandlerIsAbsent_ReturnsLastChanceHandlerWit IExceptionHandler handler = ExceptionServices.GetHandler(services); // Assert - Assert.IsType(handler); - IExceptionHandler innerHandler = ((LastChanceExceptionHandler)handler).InnerHandler; + IExceptionHandler innerHandler = Assert.IsType(handler).InnerHandler; Assert.IsType(innerHandler); } } @@ -164,8 +159,7 @@ public void GetHandlerWithConfiguration_ReturnsLastChanceHandlerWithServicesInne IExceptionHandler handler = ExceptionServices.GetHandler(configuration); // Assert - Assert.IsType(handler); - IExceptionHandler innerHandler = ((LastChanceExceptionHandler)handler).InnerHandler; + IExceptionHandler innerHandler = Assert.IsType(handler).InnerHandler; Assert.Same(expectedHandler, innerHandler); } } diff --git a/test/System.Web.Http.Test/ExceptionHandling/LastChanceExceptionHandlerTests.cs b/test/System.Web.Http.Test/ExceptionHandling/LastChanceExceptionHandlerTests.cs index 7dafd1c41..6cf3d69aa 100644 --- a/test/System.Web.Http.Test/ExceptionHandling/LastChanceExceptionHandlerTests.cs +++ b/test/System.Web.Http.Test/ExceptionHandling/LastChanceExceptionHandlerTests.cs @@ -1,7 +1,6 @@ // 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.Linq; using System.Net.Http; using System.Net.Http.Formatting; using System.Threading; @@ -114,15 +113,14 @@ public async Task HandleAsync_IfIsTopLevelCatchBlockAndCanCreateExceptionResult_ await product.HandleAsync(context, cancellationToken); // Assert - Assert.IsType(result); - ExceptionResult exceptionResult = (ExceptionResult)result; + ExceptionResult exceptionResult = Assert.IsType(result); Assert.Same(expectedException, exceptionResult.Exception); Assert.Equal(includeDetail, exceptionResult.IncludeErrorDetail); Assert.Same(expectedContentNegotiator, exceptionResult.ContentNegotiator); Assert.Same(expectedRequest, exceptionResult.Request); Assert.NotNull(exceptionResult.Formatters); - Assert.Equal(1, exceptionResult.Formatters.Count()); - Assert.Same(expectedFormatter, exceptionResult.Formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(exceptionResult.Formatters); + Assert.Same(expectedFormatter, formatter); } } diff --git a/test/System.Web.Http.Test/Filters/ActionFilterAttributeTest.cs b/test/System.Web.Http.Test/Filters/ActionFilterAttributeTest.cs index f3c77989f..4bc773db6 100644 --- a/test/System.Web.Http.Test/Filters/ActionFilterAttributeTest.cs +++ b/test/System.Web.Http.Test/Filters/ActionFilterAttributeTest.cs @@ -505,7 +505,7 @@ public async Task ExecuteActionFilterAsync_IfFaultedTaskExceptionIsUnhandled_Pre // Assert Assert.NotNull(expectedStackTrace); - Assert.True(exception.StackTrace.StartsWith(expectedStackTrace)); + Assert.StartsWith(expectedStackTrace, exception.StackTrace); } } diff --git a/test/System.Web.Http.Test/Filters/AuthorizationFilterAttributeTest.cs b/test/System.Web.Http.Test/Filters/AuthorizationFilterAttributeTest.cs index bc20692f5..7782b413a 100644 --- a/test/System.Web.Http.Test/Filters/AuthorizationFilterAttributeTest.cs +++ b/test/System.Web.Http.Test/Filters/AuthorizationFilterAttributeTest.cs @@ -66,16 +66,22 @@ public async Task ExecuteAuthorizationFilterAsync_InvokesOnActionExecutingBefore Assert.True(flagWhenContinuationInvoked.Value); } + [Fact] public async Task ExecuteAuthorizationFilterAsync_IfOnActionExecutingSetsResult_ShortCircuits() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); - Mock filterMock = new Mock(); + Mock filterMock = new Mock + { + CallBase = true, + }; + HttpResponseMessage response = new HttpResponseMessage(); filterMock.Setup(f => f.OnAuthorization(It.IsAny())).Callback(c => { c.Response = response; }); + bool continuationCalled = false; var filter = (IAuthorizationFilter)filterMock.Object; diff --git a/test/System.Web.Http.Test/Hosting/SuppressHostPrincipalMessageHandlerTest.cs b/test/System.Web.Http.Test/Hosting/SuppressHostPrincipalMessageHandlerTest.cs index 0aa37035b..26b61c047 100644 --- a/test/System.Web.Http.Test/Hosting/SuppressHostPrincipalMessageHandlerTest.cs +++ b/test/System.Web.Http.Test/Hosting/SuppressHostPrincipalMessageHandlerTest.cs @@ -14,30 +14,29 @@ namespace System.Web.Http.Hosting public class SuppressHostPrincipalMessageHandlerTest { [Fact] - public void SendAsync_DelegatesToInnerHandler() + public async Task SendAsync_DelegatesToInnerHandler() { // Arrange HttpRequestMessage request = null; - CancellationToken cancellationToken = default(CancellationToken); - Task expectedResult = new Task(() => null); + var cancellationToken = default(CancellationToken); HttpMessageHandler innerHandler = new LambdaHttpMessageHandler((r, c) => { request = r; cancellationToken = c; - return expectedResult; + return Task.FromResult(null); }); HttpMessageHandler handler = CreateProductUnderTest(innerHandler); - CancellationToken expectedCancellationToken = new CancellationToken(true); + var expectedCancellationToken = new CancellationToken(true); - using (HttpRequestMessage expectedRequest = CreateRequestWithContext()) + using (var expectedRequest = CreateRequestWithContext()) { // Act - Task result = handler.SendAsync(expectedRequest, expectedCancellationToken); + var result = await handler.SendAsync(expectedRequest, expectedCancellationToken); // Assert Assert.Same(expectedRequest, request); Assert.Equal(expectedCancellationToken, cancellationToken); - Assert.Same(expectedResult, result); + Assert.Null(result); } } @@ -59,14 +58,31 @@ await Assert.ThrowsArgumentAsync( } [Fact] - public void SendAsync_SetsCurrentPrincipalToAnonymous_BeforeCallingInnerHandler() + public async Task SendAsync_SetsCurrentPrincipalToAnonymous_BeforeCallingInnerHandler() { // Arrange + var requestContextMock = new Mock(MockBehavior.Strict); + var sequence = new MockSequence(); + var initialPrincipal = new GenericPrincipal(new GenericIdentity("generic user"), new[] { "generic role" }); IPrincipal requestContextPrincipal = null; - Mock requestContextMock = new Mock(); requestContextMock + .InSequence(sequence) + .SetupGet(c => c.Principal) + .Returns(initialPrincipal); + requestContextMock + .InSequence(sequence) .SetupSet(c => c.Principal = It.IsAny()) - .Callback((value) => requestContextPrincipal = value); + .Callback(value => requestContextPrincipal = value); + + // SendAsync also restores the old principal. + requestContextMock + .InSequence(sequence) + .SetupGet(c => c.Principal) + .Returns(requestContextPrincipal); + requestContextMock + .InSequence(sequence) + .SetupSet(c => c.Principal = initialPrincipal); + IPrincipal principalBeforeInnerHandler = null; HttpMessageHandler inner = new LambdaHttpMessageHandler((ignore1, ignore2) => { @@ -75,17 +91,18 @@ public void SendAsync_SetsCurrentPrincipalToAnonymous_BeforeCallingInnerHandler( }); HttpMessageHandler handler = CreateProductUnderTest(inner); - using (HttpRequestMessage request = new HttpRequestMessage()) + using (var request = new HttpRequestMessage()) { request.SetRequestContext(requestContextMock.Object); // Act - handler.SendAsync(request, CancellationToken.None); + await handler.SendAsync(request, CancellationToken.None); } // Assert + Assert.Equal(requestContextPrincipal, principalBeforeInnerHandler); Assert.NotNull(principalBeforeInnerHandler); - IIdentity identity = principalBeforeInnerHandler.Identity; + var identity = principalBeforeInnerHandler.Identity; Assert.NotNull(identity); Assert.False(identity.IsAuthenticated); Assert.Null(identity.Name); diff --git a/test/System.Web.Http.Test/HttpConfigurationExtensionsTest.cs b/test/System.Web.Http.Test/HttpConfigurationExtensionsTest.cs index 12fbcf5b7..a829ccdaf 100644 --- a/test/System.Web.Http.Test/HttpConfigurationExtensionsTest.cs +++ b/test/System.Web.Http.Test/HttpConfigurationExtensionsTest.cs @@ -164,8 +164,8 @@ public void MapHttpAttributeRoutes_AddsMultipleRoutesFromAttributes() // Assert var routes = config.GetAttributeRoutes(); Assert.Equal(2, routes.Count); - Assert.Single(routes.Where(route => route.RouteTemplate == "controller/get1")); - Assert.Single(routes.Where(route => route.RouteTemplate == "controller/get2")); + Assert.Single(routes, route => route.RouteTemplate == "controller/get1"); + Assert.Single(routes, route => route.RouteTemplate == "controller/get2"); } [Fact] @@ -179,8 +179,8 @@ public void MapHttpAttributeRoutes_IsDeferred() config.Services.Clear(typeof(IHttpActionSelector)); config.Services.Clear(typeof(IActionValueBinder)); - // Call Map, ensure that it's not touching any services yet since all work is deferred. - // This is important since these services aren't ready to be used until after config is finalized. + // Call Map, ensure that it's not touching any services yet since all work is deferred. + // This is important since these services aren't ready to be used until after config is finalized. // Else we may end up caching objects prematurely. config.MapHttpAttributeRoutes(); diff --git a/test/System.Web.Http.Test/HttpErrorKeysTest.cs b/test/System.Web.Http.Test/HttpErrorKeysTest.cs index 61579fec6..d8800bce8 100644 --- a/test/System.Web.Http.Test/HttpErrorKeysTest.cs +++ b/test/System.Web.Http.Test/HttpErrorKeysTest.cs @@ -5,14 +5,14 @@ namespace System.Web.Http { - class HttpErrorKeysTest + public class HttpErrorKeysTest { public static TheoryDataSet, string> ErrorKeys { get { return new TheoryDataSet, string> - { + { { () => HttpErrorKeys.MessageKey, "Message" }, { () => HttpErrorKeys.MessageDetailKey, "MessageDetail" }, { () => HttpErrorKeys.ModelStateKey, "ModelState" }, diff --git a/test/System.Web.Http.Test/HttpRequestMessageExtensionsTest.cs b/test/System.Web.Http.Test/HttpRequestMessageExtensionsTest.cs index 9bb50cfb4..9ccc7c7d6 100644 --- a/test/System.Web.Http.Test/HttpRequestMessageExtensionsTest.cs +++ b/test/System.Web.Http.Test/HttpRequestMessageExtensionsTest.cs @@ -795,8 +795,8 @@ public void RegisterForDispose_WhenResourceListDoesNotExist_CreatesListAndAddsRe request.RegisterForDispose(disposable); var list = Assert.IsType>(request.Properties[HttpPropertyKeys.DisposableRequestResourcesKey]); - Assert.Equal(1, list.Count); - Assert.Same(disposable, list[0]); + IDisposable item = Assert.Single(list); + Assert.Same(disposable, item); } [Fact] @@ -810,8 +810,8 @@ public void RegisterForDispose_WhenResourceListExists_AddsResource() request.RegisterForDispose(disposable); Assert.Same(list, request.Properties[HttpPropertyKeys.DisposableRequestResourcesKey]); - Assert.Equal(1, list.Count); - Assert.Same(disposable, list[0]); + IDisposable item = Assert.Single(list); + Assert.Same(disposable, item); } [Fact] @@ -1025,7 +1025,7 @@ public void IsLocal_ReturnsFalse_WhenNeitherContextNorPropertyArePresent() bool isLocal = request.IsLocal(); // Assert - Assert.Equal(false, isLocal); + Assert.False(isLocal); } } diff --git a/test/System.Web.Http.Test/HttpRouteCollectionExtensionsTest.cs b/test/System.Web.Http.Test/HttpRouteCollectionExtensionsTest.cs index a546120e4..2c3ac1c8f 100644 --- a/test/System.Web.Http.Test/HttpRouteCollectionExtensionsTest.cs +++ b/test/System.Web.Http.Test/HttpRouteCollectionExtensionsTest.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; -using System.Threading; using System.Web.Http.Batch; using System.Web.Http.Routing; using Microsoft.TestCommon; @@ -169,7 +168,7 @@ public void IgnoreRouteWithoutConstraints() Assert.NotNull(route); Assert.Equal("SomeRouteTemplate", route.RouteTemplate); Assert.IsType(route.Handler); - Assert.True(route.Defaults.Count == 0); + Assert.Empty(route.Defaults); Assert.Empty(route.Constraints); } @@ -188,7 +187,7 @@ public void IgnoreRouteWithConstraints() Assert.NotNull(route); Assert.Equal("SomeRouteTemplate", route.RouteTemplate); Assert.IsType(route.Handler); - Assert.True(route.Defaults.Count == 0); + Assert.Empty(route.Defaults); Assert.Single(route.Constraints); Assert.Equal("DefaultFoo", route.Constraints["Foo"]); } diff --git a/test/System.Web.Http.Test/HttpRouteCollectionTest.cs b/test/System.Web.Http.Test/HttpRouteCollectionTest.cs index 92454dc61..8e59cdc0c 100644 --- a/test/System.Web.Http.Test/HttpRouteCollectionTest.cs +++ b/test/System.Web.Http.Test/HttpRouteCollectionTest.cs @@ -21,7 +21,7 @@ public void HttpRouteCollection_Dispose_UniquifiesHandlers() handler1.As().Setup(c => c.Dispose()).Verifiable(); var handler2 = new Mock(); - handler1.As().Setup(c => c.Dispose()).Verifiable(); + handler2.As().Setup(c => c.Dispose()).Verifiable(); var route1 = new Mock(); route1.SetupGet(r => r.Handler).Returns(handler1.Object); diff --git a/test/System.Web.Http.Test/HttpServerTest.cs b/test/System.Web.Http.Test/HttpServerTest.cs index 2f5fc5ebf..72a5a1741 100644 --- a/test/System.Web.Http.Test/HttpServerTest.cs +++ b/test/System.Web.Http.Test/HttpServerTest.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.Collections.Generic; -using System.Linq; using System.Net; using System.Net.Http; using System.Security.Principal; @@ -150,12 +149,11 @@ public void ExceptionLoggerGet_IfUnset_ReturnsExceptionLoggerFromConfiguration() IExceptionLogger exceptionLogger = product.ExceptionLogger; // Assert - Assert.IsType(exceptionLogger); - CompositeExceptionLogger compositeLogger = (CompositeExceptionLogger)exceptionLogger; + CompositeExceptionLogger compositeLogger = Assert.IsType(exceptionLogger); IEnumerable loggers = compositeLogger.Loggers; Assert.NotNull(loggers); - Assert.Equal(1, loggers.Count()); - Assert.Same(expectedExceptionLogger, loggers.Single()); + IExceptionLogger logger = Assert.Single(loggers); + Assert.Same(expectedExceptionLogger, logger); } } } @@ -176,8 +174,7 @@ public void ExceptionHandlerGet_IfUnset_UsesExceptionHandlerFromConfiguration() IExceptionHandler exceptionHandler = product.ExceptionHandler; // Assert - Assert.IsType(exceptionHandler); - LastChanceExceptionHandler lastChanceHandler = (LastChanceExceptionHandler)exceptionHandler; + LastChanceExceptionHandler lastChanceHandler = Assert.IsType(exceptionHandler); Assert.Same(expectedExceptionHandler, lastChanceHandler.InnerHandler); } } @@ -469,7 +466,7 @@ public async Task SendAsync_IfExceptionHandlerSetsNullResult_PropogatesFaultedTa Assert.Same(expectedException, exception); Assert.NotNull(exception.StackTrace); - Assert.True(exception.StackTrace.StartsWith(expectedStackTrace)); + Assert.StartsWith(expectedStackTrace, exception.StackTrace); } } diff --git a/test/System.Web.Http.Test/Internal/TypeActivatorTest.cs b/test/System.Web.Http.Test/Internal/TypeActivatorTest.cs index 419b66eae..18591819b 100644 --- a/test/System.Web.Http.Test/Internal/TypeActivatorTest.cs +++ b/test/System.Web.Http.Test/Internal/TypeActivatorTest.cs @@ -28,7 +28,7 @@ public static TheoryDataSet ValidTypeParameters { typeof(Dictionary), typeof(IDictionary)}, { typeof(HttpRequestMessage), typeof(HttpRequestMessage)}, { typeof(HttpConfiguration), typeof(HttpConfiguration)}, - { typeof(ReflectedHttpActionDescriptor), typeof(HttpActionDescriptor) }, + { typeof(ReflectedHttpActionDescriptor), typeof(HttpActionDescriptor) }, { typeof(ApiControllerActionSelector), typeof(IHttpActionSelector)}, { typeof(ApiControllerActionInvoker), typeof(IHttpActionInvoker)}, { typeof(List), typeof(IEnumerable)}, @@ -36,9 +36,27 @@ public static TheoryDataSet ValidTypeParameters } } + public static TheoryDataSet ValidInstanceTypeParameters + { + get + { + return new TheoryDataSet + { + { typeof(List) }, + { typeof(Dictionary) }, + { typeof(HttpRequestMessage) }, + { typeof(HttpConfiguration) }, + { typeof(ReflectedHttpActionDescriptor) }, + { typeof(ApiControllerActionSelector) }, + { typeof(ApiControllerActionInvoker) }, + { typeof(List) }, + }; + } + } + [Theory] - [PropertyData("ValidTypeParameters")] - public void CreateType(Type instanceType, Type baseType) + [PropertyData("ValidInstanceTypeParameters")] + public void CreateType(Type instanceType) { // Arrange Func instanceDelegate = TypeActivator.Create(instanceType); @@ -74,8 +92,8 @@ public void CreateTypeInvalidThrowsInvalidOperation(Type type) } [Theory] - [PropertyData("ValidTypeParameters")] - public void CreateOfT(Type instanceType, Type baseType) + [PropertyData("ValidInstanceTypeParameters")] + public void CreateOfT(Type instanceType) { // Arrange Type activatorType = typeof(TypeActivator); diff --git a/test/System.Web.Http.Test/Metadata/Providers/AssociatedMetadataProviderTest.cs b/test/System.Web.Http.Test/Metadata/Providers/AssociatedMetadataProviderTest.cs index 23bdcac8d..32475aa5f 100644 --- a/test/System.Web.Http.Test/Metadata/Providers/AssociatedMetadataProviderTest.cs +++ b/test/System.Web.Http.Test/Metadata/Providers/AssociatedMetadataProviderTest.cs @@ -36,24 +36,24 @@ public void GetMetadataForPropertiesCreatesMetadataForAllPropertiesOnModelWithPr provider.GetMetadataForProperties(model, typeof(PropertyModel)).ToList(); // Call ToList() to force the lazy evaluation to evaluate // Assert - CreateMetadataPrototypeParams local = - provider.CreateMetadataPrototypeLog.Single(m => m.ContainerType == typeof(PropertyModel) && - m.PropertyName == "LocalAttributes"); + CreateMetadataPrototypeParams local = Assert.Single( + provider.CreateMetadataPrototypeLog, + m => m.ContainerType == typeof(PropertyModel) && m.PropertyName == "LocalAttributes"); Assert.Equal(typeof(int), local.ModelType); - Assert.True(local.Attributes.Any(a => a is RequiredAttribute)); + Assert.Contains(local.Attributes, a => a is RequiredAttribute); - CreateMetadataPrototypeParams metadata = - provider.CreateMetadataPrototypeLog.Single(m => m.ContainerType == typeof(PropertyModel) && - m.PropertyName == "MetadataAttributes"); + CreateMetadataPrototypeParams metadata = Assert.Single( + provider.CreateMetadataPrototypeLog, + m => m.ContainerType == typeof(PropertyModel) && m.PropertyName == "MetadataAttributes"); Assert.Equal(typeof(string), metadata.ModelType); - Assert.True(metadata.Attributes.Any(a => a is RangeAttribute)); + Assert.Contains(metadata.Attributes, a => a is RangeAttribute); - CreateMetadataPrototypeParams mixed = - provider.CreateMetadataPrototypeLog.Single(m => m.ContainerType == typeof(PropertyModel) && - m.PropertyName == "MixedAttributes"); + CreateMetadataPrototypeParams mixed = Assert.Single( + provider.CreateMetadataPrototypeLog, + m => m.ContainerType == typeof(PropertyModel) && m.PropertyName == "MixedAttributes"); Assert.Equal(typeof(double), mixed.ModelType); - Assert.True(mixed.Attributes.Any(a => a is RequiredAttribute)); - Assert.True(mixed.Attributes.Any(a => a is RangeAttribute)); + Assert.Contains(mixed.Attributes, a => a is RequiredAttribute); + Assert.Contains(mixed.Attributes, a => a is RangeAttribute); } [Fact] @@ -130,7 +130,10 @@ public void GetMetadataForPropertyWithLocalAttributes() // Assert Assert.Same(metadata, result); - Assert.True(provider.CreateMetadataPrototypeLog.Single(parameters => parameters.PropertyName == "LocalAttributes").Attributes.Any(a => a is RequiredAttribute)); + CreateMetadataPrototypeParams metadataPrototypeParams = Assert.Single( + provider.CreateMetadataPrototypeLog, + parameters => parameters.PropertyName == "LocalAttributes"); + Assert.Contains(metadataPrototypeParams.Attributes, a => a is RequiredAttribute); } [Fact] @@ -146,8 +149,10 @@ public void GetMetadataForPropertyWithMetadataAttributes() // Assert Assert.Same(metadata, result); - CreateMetadataPrototypeParams parms = provider.CreateMetadataPrototypeLog.Single(p => p.PropertyName == "MetadataAttributes"); - Assert.True(parms.Attributes.Any(a => a is RangeAttribute)); + CreateMetadataPrototypeParams parms = Assert.Single( + provider.CreateMetadataPrototypeLog, + parameters => parameters.PropertyName == "MetadataAttributes"); + Assert.Contains(parms.Attributes, a => a is RangeAttribute); } [Fact] @@ -163,9 +168,11 @@ public void GetMetadataForPropertyWithMixedAttributes() // Assert Assert.Same(metadata, result); - CreateMetadataPrototypeParams parms = provider.CreateMetadataPrototypeLog.Single(p => p.PropertyName == "MixedAttributes"); - Assert.True(parms.Attributes.Any(a => a is RequiredAttribute)); - Assert.True(parms.Attributes.Any(a => a is RangeAttribute)); + CreateMetadataPrototypeParams parms = Assert.Single( + provider.CreateMetadataPrototypeLog, + p => p.PropertyName == "MixedAttributes"); + Assert.Contains(parms.Attributes, a => a is RequiredAttribute); + Assert.Contains(parms.Attributes, a => a is RangeAttribute); } // GetMetadataForType @@ -194,8 +201,10 @@ public void GetMetadataForTypeIncludesAttributesOnType() // Assert Assert.Same(metadata, result); - CreateMetadataPrototypeParams parms = provider.CreateMetadataPrototypeLog.Single(p => p.ModelType == typeof(TypeModel)); - Assert.True(parms.Attributes.Any(a => a is ReadOnlyAttribute)); + CreateMetadataPrototypeParams parms = Assert.Single( + provider.CreateMetadataPrototypeLog, + p => p.ModelType == typeof(TypeModel)); + Assert.Contains(parms.Attributes, a => a is ReadOnlyAttribute); } // Helpers diff --git a/test/System.Web.Http.Test/Metadata/Providers/DataAnnotationsModelMetadataProviderTest.cs b/test/System.Web.Http.Test/Metadata/Providers/DataAnnotationsModelMetadataProviderTest.cs index 8017f3eed..d255c4dcd 100644 --- a/test/System.Web.Http.Test/Metadata/Providers/DataAnnotationsModelMetadataProviderTest.cs +++ b/test/System.Web.Http.Test/Metadata/Providers/DataAnnotationsModelMetadataProviderTest.cs @@ -21,9 +21,9 @@ public void GetMetadataForPropertiesSetTypesAndPropertyNames() IEnumerable result = provider.GetMetadataForProperties("foo", typeof(string)); // Assert - Assert.True(result.Any(m => m.ModelType == typeof(int) + Assert.Contains(result, m => m.ModelType == typeof(int) && m.PropertyName == "Length" - && (int)m.Model == 3)); + && (int)m.Model == 3); } [Fact] diff --git a/test/System.Web.Http.Test/ModelBinding/Binders/CollectionModelBinderTest.cs b/test/System.Web.Http.Test/ModelBinding/Binders/CollectionModelBinderTest.cs index 0934be147..e3f0c5ee9 100644 --- a/test/System.Web.Http.Test/ModelBinding/Binders/CollectionModelBinderTest.cs +++ b/test/System.Web.Http.Test/ModelBinding/Binders/CollectionModelBinderTest.cs @@ -326,8 +326,7 @@ public void BindingUnboundedCollection_WithRecursiveRelation_ProducesSingleLengt // Assert Assert.True(result); - List boundModel = - Assert.IsType>(bindingContext.Model); + List boundModel = Assert.IsType>(bindingContext.Model); Person type = Assert.Single(boundModel); Assert.Null(type.Name); } diff --git a/test/System.Web.Http.Test/ModelBinding/Binders/MutableObjectModelBinderTest.cs b/test/System.Web.Http.Test/ModelBinding/Binders/MutableObjectModelBinderTest.cs index cafd43265..6f3991053 100644 --- a/test/System.Web.Http.Test/ModelBinding/Binders/MutableObjectModelBinderTest.cs +++ b/test/System.Web.Http.Test/ModelBinding/Binders/MutableObjectModelBinderTest.cs @@ -347,14 +347,13 @@ public void ProcessDto_BindRequiredFieldMissing_RaisesModelError() // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); - Assert.Equal(1, modelStateDictionary.Count); + Assert.Single(modelStateDictionary); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); - Assert.Equal(1, modelState.Errors.Count); - ModelError modelError = modelState.Errors[0]; + ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The Age property is required.", modelError.ErrorMessage); @@ -400,14 +399,13 @@ public void ProcessDto_BindRequiredFieldNull_RaisesModelError() // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); - Assert.Equal(1, modelStateDictionary.Count); + Assert.Single(modelStateDictionary); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); - Assert.Equal(1, modelState.Errors.Count); - ModelError modelError = modelState.Errors[0]; + ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("A value is required.", modelError.ErrorMessage); @@ -443,18 +441,16 @@ public void ProcessDto_RequiredFieldMissing_RaisesModelError() // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); - Assert.Equal(1, modelState.Errors.Count); - ModelError modelError = modelState.Errors[0]; + ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The Age field is required.", modelError.ErrorMessage); // Check City error. Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState)); - Assert.Equal(1, modelState.Errors.Count); - modelError = modelState.Errors[0]; + modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The City field is required.", modelError.ErrorMessage); @@ -492,14 +488,13 @@ public void ProcessDto_RequiredFieldNull_RaisesModelError() // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); - Assert.Equal(1, modelStateDictionary.Count); + Assert.Single(modelStateDictionary); // Check City error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState)); - Assert.Equal(1, modelState.Errors.Count); - ModelError modelError = modelState.Errors[0]; + ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The City field is required.", modelError.ErrorMessage); @@ -529,14 +524,13 @@ public void ProcessDto_RequiredFieldMissing_RaisesModelErrorWithMessage() // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); - Assert.Equal(1, modelStateDictionary.Count); + Assert.Single(modelStateDictionary); // Check ValueTypeRequired error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.ValueTypeRequired", out modelState)); - Assert.Equal(1, modelState.Errors.Count); - ModelError modelError = modelState.Errors[0]; + ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); @@ -570,14 +564,13 @@ public void ProcessDto_RequiredFieldNull_RaisesModelErrorWithMessage() // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); - Assert.Equal(1, modelStateDictionary.Count); + Assert.Single(modelStateDictionary); // Check ValueTypeRequired error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.ValueTypeRequired", out modelState)); - Assert.Equal(1, modelState.Errors.Count); - ModelError modelError = modelState.Errors[0]; + ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); @@ -801,10 +794,10 @@ public void SetProperty_SettingNullableTypeToNull_RequiredValidatorNotPresent_Pr // Assert Assert.False(bindingContext.ModelState.IsValid); - Assert.Equal(1, bindingContext.ModelState["foo.NameNoAttribute"].Errors.Count); - Assert.Equal("This is a different exception." + Environment.NewLine - + "Parameter name: value", - bindingContext.ModelState["foo.NameNoAttribute"].Errors[0].Exception.Message); + ModelError modelError = Assert.Single(bindingContext.ModelState["foo.NameNoAttribute"].Errors); + Assert.Equal( + "This is a different exception." + Environment.NewLine + "Parameter name: value", + modelError.Exception.Message); } [Fact] @@ -830,8 +823,8 @@ public void SetProperty_SettingNullableTypeToNull_RequiredValidatorPresent_Prope // Assert Assert.False(bindingContext.ModelState.IsValid); - Assert.Equal(1, bindingContext.ModelState["foo.Name"].Errors.Count); - Assert.Equal("This message comes from the [Required] attribute.", bindingContext.ModelState["foo.Name"].Errors[0].ErrorMessage); + ModelError modelError = Assert.Single(bindingContext.ModelState["foo.Name"].Errors); + Assert.Equal("This message comes from the [Required] attribute.", modelError.ErrorMessage); } private static ModelMetadata GetMetadataForCanUpdateProperty(string propertyName) diff --git a/test/System.Web.Http.Test/ModelBinding/DefaultActionValueBinderTest.cs b/test/System.Web.Http.Test/ModelBinding/DefaultActionValueBinderTest.cs index a41f65b84..bfd197b32 100644 --- a/test/System.Web.Http.Test/ModelBinding/DefaultActionValueBinderTest.cs +++ b/test/System.Web.Http.Test/ModelBinding/DefaultActionValueBinderTest.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.ComponentModel; -using System.Linq; using System.Net.Http; using System.Reflection; using System.Threading; @@ -13,7 +12,7 @@ namespace System.Web.Http.ModelBinding { - // These tests primarily focus on getting the right binding contract. They don't actually execute the contract. + // These tests primarily focus on getting the right binding contract. They don't actually execute the contract. public class DefaultActionValueBinderTest { [Fact] @@ -37,7 +36,7 @@ public void Check_Int_Is_ModelBound() var binding = binder.GetBinding(GetAction("Action_Int")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -51,7 +50,7 @@ public void Check_Config_Override_Use_Formatters() var binding = binder.GetBinding(GetAction("Action_Int", config)); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsBody(binding, 0); } @@ -65,7 +64,7 @@ public void Check_Explicit_Int_Is_ModelBound() var binding = binder.GetBinding(GetAction("Action_Int_FromUri")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -94,7 +93,7 @@ public void Check_String_TypeConverter_Is_ModelBound() var binding = binder.GetBinding(GetAction("Action_ComplexTypeWithStringConverter")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -107,7 +106,7 @@ public void Check_String_TypeConverter_With_Body_Override() var binding = binder.GetBinding(GetAction("Action_ComplexTypeWithStringConverter_Body_Override")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsBody(binding, 0); } @@ -120,7 +119,7 @@ public void Check_NullableInt_Is_ModelBound() var binding = binder.GetBinding(GetAction("Action_NullableInt")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -133,7 +132,7 @@ public void Check_Nullable_ValueType_Is_FromBody() var binding = binder.GetBinding(GetAction("Action_Nullable_ValueType")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsBody(binding, 0); } @@ -147,7 +146,7 @@ public void Check_IntArray_Is_FromBody() var binding = binder.GetBinding(GetAction("Action_IntArray")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsBody(binding, 0); } @@ -161,7 +160,7 @@ public void Check_SimpleType_Body() var binding = binder.GetBinding(GetAction("Action_SimpleType_Body")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsBody(binding, 0); } @@ -175,7 +174,7 @@ public void Check_Empty_Action() var binding = binder.GetBinding(GetAction("Action_Empty")); Assert.NotNull(binding.ParameterBindings); - Assert.Equal(0, binding.ParameterBindings.Length); + Assert.Empty(binding.ParameterBindings); } private void Action_String_String(string s1, string s2) { } @@ -201,7 +200,7 @@ public void Check_Complex_Type_FromBody() var binding = binder.GetBinding(GetAction("Action_Complex_Type")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsBody(binding, 0); } @@ -214,7 +213,7 @@ public void Check_Config_Override_Use_ModelBinding() var binding = binder.GetBinding(GetAction("Action_Complex_Type", config)); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -228,7 +227,7 @@ public void Check_Complex_ValueType_FromBody() var binding = binder.GetBinding(GetAction("Action_Complex_ValueType")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsBody(binding, 0); } @@ -243,7 +242,7 @@ public void Check_Customer_Binder() var binding = binder.GetBinding(GetAction("Action_Default_Custom_Model_Binder")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -257,7 +256,7 @@ public void Check_Complex_Type_FromUri() var binding = binder.GetBinding(GetAction("Action_Complex_Type_Uri")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -268,8 +267,8 @@ public void Check_Two_Complex_Types_FromBody() { DefaultActionValueBinder binder = new DefaultActionValueBinder(); - // It's illegal to have multiple parameters from the body. - // But we should still be able to get a binding for it. We just can't execute it. + // It's illegal to have multiple parameters from the body. + // But we should still be able to get a binding for it. We just can't execute it. var binding = binder.GetBinding(GetAction("Action_Two_Complex_Types")); Assert.Equal(2, binding.ParameterBindings.Length); @@ -300,7 +299,7 @@ public void Check_Cancellation_Token() var binding = binder.GetBinding(GetAction("Action_CancellationToken")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsCancellationToken(binding, 0); } @@ -318,15 +317,15 @@ public void Check_CustomModelBinder_On_Parameter() var binding = binder.GetBinding(GetAction("Action_CustomModelBinder_On_Parameter_WithProvider", config)); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); ModelBinderParameterBinding p = (ModelBinderParameterBinding)binding.ParameterBindings[0]; Assert.IsType(p.Binder); // Since the ModelBinderAttribute didn't specify the valueproviders, we should pull those from config. - Assert.Equal(1, p.ValueProviderFactories.Count()); - Assert.IsType(p.ValueProviderFactories.First()); + ValueProviderFactory valueProviderFactory = Assert.Single(p.ValueProviderFactories); + Assert.IsType(valueProviderFactory); } // Model binder attribute is on the type's declaration. @@ -339,7 +338,7 @@ public void Check_Parameter_With_ModelBinder_Attribute_On_Type() var binding = binder.GetBinding(GetAction("Action_ComplexParameter_With_ModelBinder")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -352,8 +351,8 @@ public void Error_Conflicting_Attributes() var binding = binder.GetBinding(GetAction("Action_Conflicting_Attributes")); - // Have 2 attributes that conflict with each other. Still get the contract, but it has an error in it. - Assert.Equal(1, binding.ParameterBindings.Length); + // Have 2 attributes that conflict with each other. Still get the contract, but it has an error in it. + Assert.Single(binding.ParameterBindings); AssertIsError(binding, 0); } @@ -370,8 +369,8 @@ public void Check_Closest_Attribute_Wins() var binding = binder.GetBinding(GetAction("Action_Closest_Attribute_Wins")); - // Have 2 attributes that conflict with each other. Still get the contract, but it has an error in it. - Assert.Equal(1, binding.ParameterBindings.Length); + // Have 2 attributes that conflict with each other. Still get the contract, but it has an error in it. + Assert.Single(binding.ParameterBindings); AssertIsModelBound(binding, 0); } @@ -384,7 +383,7 @@ public void Check_HttpContent() var binding = binder.GetBinding(GetAction("Action_HttpContent_Parameter")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsError(binding, 0); } @@ -397,7 +396,7 @@ public void Check_Derived_HttpContent() var binding = binder.GetBinding(GetAction("Action_Derived_HttpContent_Parameter")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsError(binding, 0); } @@ -410,7 +409,7 @@ public void Check_Request_Parameter() var binding = binder.GetBinding(GetAction("Action_Request_Parameter")); - Assert.Equal(1, binding.ParameterBindings.Length); + Assert.Single(binding.ParameterBindings); AssertIsCustomBinder(binding, 0); } @@ -424,8 +423,8 @@ public void Check_CustomBindingAttribute() var binding = binder.GetBinding(GetAction("Action_CustomBindingAttribute")); - Assert.Equal(1, binding.ParameterBindings.Length); - Assert.Same(CustomBindingAttribute.MockBinding, binding.ParameterBindings[0]); + HttpParameterBinding parameterBinding = Assert.Single(binding.ParameterBindings); + Assert.Same(CustomBindingAttribute.MockBinding, parameterBinding); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] @@ -472,7 +471,7 @@ private void AssertIsModelBound(HttpActionBinding binding, int paramIdx) Assert.False(p.WillReadBody); } - // Assert that the binding contract says the given parameter will be bound to the cancellation token. + // Assert that the binding contract says the given parameter will be bound to the cancellation token. private void AssertIsCancellationToken(HttpActionBinding binding, int paramIdx) { AssertIsCustomBinder(binding, paramIdx); @@ -496,7 +495,7 @@ private void AssertIsCustomBinder(HttpActionBinding binding, int paramIdx) } - // Helper to get an ActionDescriptor for a method name. + // Helper to get an ActionDescriptor for a method name. private HttpActionDescriptor GetAction(string name) { return GetAction(name, new HttpConfiguration()); @@ -530,7 +529,7 @@ class ComplexTypeWithModelBinder { } - // Add Type converter for string, which causes the type to be viewed as a Simple type. + // Add Type converter for string, which causes the type to be viewed as a Simple type. [TypeConverter(typeof(MyTypeConverter))] public class ComplexTypeWithStringConverter { diff --git a/test/System.Web.Http.Test/ModelBinding/FormDataCollectionExtensionsTest.cs b/test/System.Web.Http.Test/ModelBinding/FormDataCollectionExtensionsTest.cs index 4357b212f..6e29a32a1 100644 --- a/test/System.Web.Http.Test/ModelBinding/FormDataCollectionExtensionsTest.cs +++ b/test/System.Web.Http.Test/ModelBinding/FormDataCollectionExtensionsTest.cs @@ -299,7 +299,7 @@ public async Task ReadAs_WithHttpActionContext() int actual = formData.ReadAs(actionContext); // Assert - Assert.Equal(expected, actual); + Assert.Equal(expected, actual); } } @@ -319,7 +319,7 @@ public async Task ReadAs_WithModelNameAndHttpActionContext() int actual = (int)formData.ReadAs(typeof(int), "a", actionContext); // Assert - Assert.Equal(expected, actual); + Assert.Equal(expected, actual); } } @@ -343,7 +343,7 @@ public async Task Read_As_WithHttpActionContextAndCustomModelBinder() int actual = (int)formData.ReadAs(typeof(int), "a", actionContext); // Assert - Assert.Equal(expected, actual); + Assert.Equal(expected, actual); } } @@ -366,7 +366,7 @@ public async Task Read_As_NoServicesChangeInConfig() formatterLogger: (new Mock()).Object, config: configuration); // Assert - Assert.Equal(30, actual); + Assert.Equal(30, actual); Assert.Same(clonedConfiguration.Services, configuration.Services); } } diff --git a/test/System.Web.Http.Test/ModelBinding/ModelBinderAttributeTest.cs b/test/System.Web.Http.Test/ModelBinding/ModelBinderAttributeTest.cs index fdda5cedc..ac4c75e4f 100644 --- a/test/System.Web.Http.Test/ModelBinding/ModelBinderAttributeTest.cs +++ b/test/System.Web.Http.Test/ModelBinding/ModelBinderAttributeTest.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.Collections.Generic; -using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.Dependencies; using System.Web.Http.ValueProviders; @@ -52,7 +51,7 @@ public void BinderType_Provided() [Fact] public void BinderType_From_DependencyResolver() { - // To test dependency resolver, the registered type and actual type should be different. + // To test dependency resolver, the registered type and actual type should be different. HttpConfiguration config = new HttpConfiguration(); var mockDependencyResolver = new Mock(); mockDependencyResolver.Setup(r => r.GetService(typeof(CustomModelBinderProvider))) @@ -93,8 +92,8 @@ public void Set_ModelBinder_And_ValueProviders() IEnumerable vpfs = attr.GetValueProviderFactories(config); Assert.IsType(attr.GetModelBinderProvider(config)); - Assert.Equal(1, vpfs.Count()); - Assert.IsType(vpfs.First()); + object valueProviderFactory = Assert.Single(vpfs); + Assert.IsType(valueProviderFactory); } [Fact] @@ -110,7 +109,7 @@ public void Get_ModelBinder_From_Empty_Attribute() IModelBinder binder = attr.GetModelBinder(config, null); // Assert - Assert.Null(attr.BinderType); // using the default + Assert.Null(attr.BinderType); // using the default Assert.NotNull(binder); Assert.IsType(binder); } diff --git a/test/System.Web.Http.Test/ModelBinding/ModelBindingEndToEndTests.cs b/test/System.Web.Http.Test/ModelBinding/ModelBindingEndToEndTests.cs index 505dcdea5..2455087f7 100644 --- a/test/System.Web.Http.Test/ModelBinding/ModelBindingEndToEndTests.cs +++ b/test/System.Web.Http.Test/ModelBinding/ModelBindingEndToEndTests.cs @@ -140,8 +140,8 @@ public async Task BindModel_WithNestedCollection() Assert.Equal("98052", address.ZipCode); address = result.Addresses[1]; - Assert.Single(address.AddressLines); - Assert.Equal("Street Address 10", address.AddressLines[0].Line); + StreetAddress streetAddress= streetAddress = Assert.Single(address.AddressLines); + Assert.Equal("Street Address 10", streetAddress.Line); Assert.Null(address.ZipCode); } diff --git a/test/System.Web.Http.Test/Results/BadRequestErrorMessageResultTests.cs b/test/System.Web.Http.Test/Results/BadRequestErrorMessageResultTests.cs index a56278c63..eceefef62 100644 --- a/test/System.Web.Http.Test/Results/BadRequestErrorMessageResultTests.cs +++ b/test/System.Web.Http.Test/Results/BadRequestErrorMessageResultTests.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.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; @@ -212,8 +211,7 @@ public async Task ExecuteAsync_ReturnsCorrectResponse_WhenContentNegotiationSucc Assert.NotNull(response); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); HttpError error = (HttpError)typedContent.Value; Assert.NotNull(error); Assert.Same(expectedMessage, error.Message); @@ -312,8 +310,7 @@ public async Task ExecuteAsync_ForApiController_ReturnsCorrectResponse_WhenConte Assert.NotNull(response); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); HttpError error = (HttpError)typedContent.Value; Assert.NotNull(error); Assert.Same(expectedMessage, error.Message); @@ -410,8 +407,8 @@ public void Formatters_ForApiController_EvaluatesLazily() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } @@ -505,8 +502,8 @@ public void Formatters_ForApiController_EvaluatesOnce() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } diff --git a/test/System.Web.Http.Test/Results/CreatedAtRouteNegotiatedContentResultTests.cs b/test/System.Web.Http.Test/Results/CreatedAtRouteNegotiatedContentResultTests.cs index 7d436232b..23c00c4f9 100644 --- a/test/System.Web.Http.Test/Results/CreatedAtRouteNegotiatedContentResultTests.cs +++ b/test/System.Web.Http.Test/Results/CreatedAtRouteNegotiatedContentResultTests.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.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; @@ -346,8 +345,7 @@ public async Task ExecuteAsync_Returns_CorrectResponse_WhenContentNegotiationSuc Assert.Equal(HttpStatusCode.Created, response.StatusCode); Assert.Same(expectedLocation, response.Headers.Location.OriginalString); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -495,8 +493,7 @@ public async Task ExecuteAsync_ForApiController_ReturnsCorrectResponse_WhenConte Assert.Equal(HttpStatusCode.Created, response.StatusCode); Assert.Same(expectedLocation, response.Headers.Location.OriginalString); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedOutputFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -632,8 +629,8 @@ public void Formatters_ForApiController_EvaluatesLazily() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } @@ -769,8 +766,8 @@ public void Formatters_ForApiController_EvaluatesOnce() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } diff --git a/test/System.Web.Http.Test/Results/CreatedNegotiatedContentResultTests.cs b/test/System.Web.Http.Test/Results/CreatedNegotiatedContentResultTests.cs index 6c7b18e1a..05bf25c68 100644 --- a/test/System.Web.Http.Test/Results/CreatedNegotiatedContentResultTests.cs +++ b/test/System.Web.Http.Test/Results/CreatedNegotiatedContentResultTests.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.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; @@ -245,8 +244,7 @@ public async Task ExecuteAsync_Returns_CorrectResponse_WhenContentNegotiationSuc Assert.Equal(HttpStatusCode.Created, response.StatusCode); Assert.Same(expectedLocation, response.Headers.Location); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -350,8 +348,7 @@ public async Task ExecuteAsync_ForApiController_ReturnsCorrectResponse_WhenConte Assert.Equal(HttpStatusCode.Created, response.StatusCode); Assert.Same(expectedLocation, response.Headers.Location); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedOutputFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -451,8 +448,8 @@ public void Formatters_ForApiController_EvaluatesLazily() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } @@ -549,8 +546,8 @@ public void Formatters_ForApiController_EvaluatesOnce() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } diff --git a/test/System.Web.Http.Test/Results/ExceptionResultTests.cs b/test/System.Web.Http.Test/Results/ExceptionResultTests.cs index 02bdab101..caf253f1a 100644 --- a/test/System.Web.Http.Test/Results/ExceptionResultTests.cs +++ b/test/System.Web.Http.Test/Results/ExceptionResultTests.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.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; @@ -245,12 +244,11 @@ public async Task ExecuteAsync_ReturnsCorrectResponse_WhenContentNegotiationSucc Assert.NotNull(response); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); HttpError error = (HttpError)typedContent.Value; Assert.NotNull(error); Assert.Equal(expectedException.Message, error.ExceptionMessage); - Assert.Same(expectedException.GetType().FullName, error.ExceptionType); + Assert.Equal(expectedException.GetType().FullName, error.ExceptionType); Assert.Equal(expectedException.StackTrace, error.StackTrace); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -294,8 +292,7 @@ public async Task ExecuteAsync_ReturnsCorrectResponse_WhenContentNegotiationSucc Assert.NotNull(response); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); HttpError error = (HttpError)typedContent.Value; Assert.NotNull(error); Assert.Null(error.ExceptionMessage); @@ -400,12 +397,11 @@ public async Task ExecuteAsync_ForApiController_ReturnsCorrectResponse_WhenConte Assert.NotNull(response); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); HttpError error = (HttpError)typedContent.Value; Assert.NotNull(error); Assert.Equal(expectedException.Message, error.ExceptionMessage); - Assert.Same(expectedException.GetType().FullName, error.ExceptionType); + Assert.Equal(expectedException.GetType().FullName, error.ExceptionType); Assert.Equal(expectedException.StackTrace, error.StackTrace); Assert.Same(expectedOutputFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -441,7 +437,7 @@ public void IncludeErrorDetail_ForApiController_EvaluatesLazily() IContentNegotiator contentNegotiator = result.ContentNegotiator; // Assert - Assert.Equal(false, result.IncludeErrorDetail); + Assert.False(result.IncludeErrorDetail); } } } @@ -531,8 +527,8 @@ public void Formatters_ForApiController_EvaluatesLazily() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } @@ -566,7 +562,7 @@ public void IncludeErrorDetail_ForApiController_EvaluatesOnce() bool includeErrorDetail = result.IncludeErrorDetail; // Assert - Assert.Equal(true, includeErrorDetail); + Assert.True(includeErrorDetail); } } @@ -659,8 +655,8 @@ public void Formatters_ForApiController_EvaluatesOnce() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } diff --git a/test/System.Web.Http.Test/Results/FormattedContentResultTests.cs b/test/System.Web.Http.Test/Results/FormattedContentResultTests.cs index 07dac7976..ab780e386 100644 --- a/test/System.Web.Http.Test/Results/FormattedContentResultTests.cs +++ b/test/System.Web.Http.Test/Results/FormattedContentResultTests.cs @@ -184,8 +184,7 @@ public async Task ExecuteAsync_Returns_CorrectResponse() Assert.NotNull(response); Assert.Equal(expectedStatusCode, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -239,8 +238,7 @@ public async Task ExecuteAsync_ForApiController_ReturnsCorrectResponse() Assert.NotNull(response); Assert.Equal(expectedStatusCode, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); diff --git a/test/System.Web.Http.Test/Results/InvalidModelStateResultTests.cs b/test/System.Web.Http.Test/Results/InvalidModelStateResultTests.cs index 536a306f2..49ce2d0b2 100644 --- a/test/System.Web.Http.Test/Results/InvalidModelStateResultTests.cs +++ b/test/System.Web.Http.Test/Results/InvalidModelStateResultTests.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.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; @@ -249,18 +248,16 @@ public async Task ExecuteAsync_ReturnsCorrectResponse_WhenContentNegotiationSucc Assert.NotNull(response); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); HttpError error = (HttpError)typedContent.Value; Assert.NotNull(error); HttpError modelStateError = error.ModelState; Assert.NotNull(modelStateError); Assert.True(modelState.ContainsKey(expectedModelStateKey)); object modelStateValue = modelStateError[expectedModelStateKey]; - Assert.IsType(typeof(string[]), modelStateValue); - string[] typedModelStateValue = (string[])modelStateValue; - Assert.Equal(1, typedModelStateValue.Length); - Assert.Same(expectedModelStateExceptionMessage, typedModelStateValue[0]); + string[] typedModelStateValues = Assert.IsType(modelStateValue); + string typedModelStateValue = Assert.Single(typedModelStateValues); + Assert.Same(expectedModelStateExceptionMessage, typedModelStateValue); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); Assert.Equal(expectedMediaType, typedContent.Headers.ContentType); @@ -309,18 +306,16 @@ public async Task ExecuteAsync_ReturnsCorrectResponse_WhenContentNegotiationSucc Assert.NotNull(response); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); HttpError error = (HttpError)typedContent.Value; Assert.NotNull(error); HttpError modelStateError = error.ModelState; Assert.NotNull(modelStateError); Assert.True(modelState.ContainsKey(expectedModelStateKey)); object modelStateValue = modelStateError[expectedModelStateKey]; - Assert.IsType(typeof(string[]), modelStateValue); - string[] typedModelStateValue = (string[])modelStateValue; - Assert.Equal(1, typedModelStateValue.Length); - Assert.Same(expectedModelStateErrorMessage, typedModelStateValue[0]); + string[] typedModelStateValues = Assert.IsType(modelStateValue); + string typedModelStateValue = Assert.Single(typedModelStateValues); + Assert.Same(expectedModelStateErrorMessage, typedModelStateValue); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); Assert.Equal(expectedMediaType, typedContent.Headers.ContentType); @@ -424,18 +419,16 @@ public async Task ExecuteAsync_ForApiController_ReturnsCorrectResponse_WhenConte Assert.NotNull(response); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); HttpError error = (HttpError)typedContent.Value; Assert.NotNull(error); HttpError modelStateError = error.ModelState; Assert.NotNull(modelStateError); Assert.True(modelState.ContainsKey(expectedModelStateKey)); object modelStateValue = modelStateError[expectedModelStateKey]; - Assert.IsType(typeof(string[]), modelStateValue); - string[] typedModelStateValue = (string[])modelStateValue; - Assert.Equal(1, typedModelStateValue.Length); - Assert.Same(expectedModelStateExceptionMessage, typedModelStateValue[0]); + string[] typedModelStateValues = Assert.IsType(modelStateValue); + string typedModelStateValue = Assert.Single(typedModelStateValues); + Assert.Same(expectedModelStateExceptionMessage, typedModelStateValue); Assert.Same(expectedOutputFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); Assert.Equal(expectedMediaType, typedContent.Headers.ContentType); @@ -470,7 +463,7 @@ public void IncludeErrorDetail_ForApiController_EvaluatesLazily() IContentNegotiator contentNegotiator = result.ContentNegotiator; // Assert - Assert.Equal(false, result.IncludeErrorDetail); + Assert.False(result.IncludeErrorDetail); } } } @@ -560,8 +553,8 @@ public void Formatters_ForApiController_EvaluatesLazily() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } @@ -595,7 +588,7 @@ public void IncludeErrorDetail_ForApiController_EvaluatesOnce() bool includeErrorDetail = result.IncludeErrorDetail; // Assert - Assert.Equal(true, includeErrorDetail); + Assert.True(includeErrorDetail); } } @@ -688,8 +681,8 @@ public void Formatters_ForApiController_EvaluatesOnce() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } diff --git a/test/System.Web.Http.Test/Results/NegotiatedContentResultTests.cs b/test/System.Web.Http.Test/Results/NegotiatedContentResultTests.cs index 05a664f42..2ccec3a23 100644 --- a/test/System.Web.Http.Test/Results/NegotiatedContentResultTests.cs +++ b/test/System.Web.Http.Test/Results/NegotiatedContentResultTests.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.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; @@ -223,8 +222,7 @@ public async Task ExecuteAsync_Returns_CorrectResponse_WhenContentNegotiationSuc Assert.NotNull(response); Assert.Equal(expectedStatusCode, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -327,8 +325,7 @@ public async Task ExecuteAsync_ForApiController_ReturnsCorrectResponse_WhenConte Assert.NotNull(response); Assert.Equal(expectedStatusCode, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedOutputFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -428,8 +425,8 @@ public void Formatters_ForApiController_EvaluatesLazily() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } @@ -528,8 +525,8 @@ public void Formatters_ForApiController_EvaluatesOnce() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } diff --git a/test/System.Web.Http.Test/Results/OkNegotiatedContentResultTests.cs b/test/System.Web.Http.Test/Results/OkNegotiatedContentResultTests.cs index 698dd0650..b8e99979a 100644 --- a/test/System.Web.Http.Test/Results/OkNegotiatedContentResultTests.cs +++ b/test/System.Web.Http.Test/Results/OkNegotiatedContentResultTests.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.Collections.Generic; -using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; @@ -192,8 +191,7 @@ public async Task ExecuteAsync_Returns_CorrectResponse_WhenContentNegotiationSuc Assert.NotNull(response); Assert.Equal(HttpStatusCode.OK, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -292,8 +290,7 @@ public async Task ExecuteAsync_ForApiController_ReturnsCorrectResponse_WhenConte Assert.NotNull(response); Assert.Equal(HttpStatusCode.OK, response.StatusCode); HttpContent content = response.Content; - Assert.IsType>(content); - ObjectContent typedContent = (ObjectContent)content; + ObjectContent typedContent = Assert.IsType>(content); Assert.Same(expectedContent, typedContent.Value); Assert.Same(expectedOutputFormatter, typedContent.Formatter); Assert.NotNull(typedContent.Headers); @@ -387,8 +384,8 @@ public void Formatters_ForApiController_EvaluatesLazily() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } @@ -481,8 +478,8 @@ public void Formatters_ForApiController_EvaluatesOnce() // Assert Assert.NotNull(formatters); - Assert.Equal(1, formatters.Count()); - Assert.Same(expectedFormatter, formatters.Single()); + MediaTypeFormatter formatter = Assert.Single(formatters); + Assert.Same(expectedFormatter, formatter); } } } diff --git a/test/System.Web.Http.Test/Routing/DirectRouteProviderContextTests.cs b/test/System.Web.Http.Test/Routing/DirectRouteProviderContextTests.cs index bec090eba..891f2ba2a 100644 --- a/test/System.Web.Http.Test/Routing/DirectRouteProviderContextTests.cs +++ b/test/System.Web.Http.Test/Routing/DirectRouteProviderContextTests.cs @@ -43,7 +43,7 @@ public void CreateBuilderWithResolverAndBuild_Throws_WhenConstraintResolverRetur var ex = Assert.Throws( () => BuildWithResolver(@"hello/{param:constraint}", constraintResolver: constraintResolver.Object)); Assert.Matches( - "The inline constraint resolver of type 'ObjectProxy(_\\d+)?' was unable to resolve the following inline constraint: 'constraint'.", + "The inline constraint resolver of type 'IInlineConstraintResolverProxy' was unable to resolve the following inline constraint: 'constraint'.", ex.Message); } diff --git a/test/System.Web.Http.Test/Routing/MediaTypeFormatterExtensionsTests.cs b/test/System.Web.Http.Test/Routing/MediaTypeFormatterExtensionsTests.cs index 93e5aad40..76c144c85 100644 --- a/test/System.Web.Http.Test/Routing/MediaTypeFormatterExtensionsTests.cs +++ b/test/System.Web.Http.Test/Routing/MediaTypeFormatterExtensionsTests.cs @@ -23,10 +23,10 @@ public void AddUriPathExtensionMapping_MediaTypeHeaderValue_UpdatesMediaTypeMapp mockFormatter.AddUriPathExtensionMapping("ext", new MediaTypeHeaderValue("application/test")); - Assert.Equal(1, mockFormatter.MediaTypeMappings.Count); - Assert.IsType(typeof(UriPathExtensionMapping), mockFormatter.MediaTypeMappings[0]); - Assert.Equal("ext", (mockFormatter.MediaTypeMappings[0] as UriPathExtensionMapping).UriPathExtension); - Assert.Equal("application/test", (mockFormatter.MediaTypeMappings[0] as UriPathExtensionMapping).MediaType.MediaType); + MediaTypeMapping mediaTypeMapping = Assert.Single(mockFormatter.MediaTypeMappings); + UriPathExtensionMapping uriPathExtensionMapping = Assert.IsType(mediaTypeMapping); + Assert.Equal("ext", uriPathExtensionMapping.UriPathExtension); + Assert.Equal("application/test", uriPathExtensionMapping.MediaType.MediaType); } [Fact] @@ -43,10 +43,10 @@ public void AddUriPathExtensionMapping_MediaType_UpdatesMediaTypeMappingsCollect mockFormatter.AddUriPathExtensionMapping("ext", "application/test"); - Assert.Equal(1, mockFormatter.MediaTypeMappings.Count); - Assert.IsType(typeof(UriPathExtensionMapping), mockFormatter.MediaTypeMappings[0]); - Assert.Equal("ext", (mockFormatter.MediaTypeMappings[0] as UriPathExtensionMapping).UriPathExtension); - Assert.Equal("application/test", (mockFormatter.MediaTypeMappings[0] as UriPathExtensionMapping).MediaType.MediaType); + MediaTypeMapping mediaTypeMapping = Assert.Single(mockFormatter.MediaTypeMappings); + UriPathExtensionMapping uriPathExtensionMapping = Assert.IsType(mediaTypeMapping); + Assert.Equal("ext", uriPathExtensionMapping.UriPathExtension); + Assert.Equal("application/test", uriPathExtensionMapping.MediaType.MediaType); } } } diff --git a/test/System.Web.Http.Test/Routing/UriPathExtensionMappingTests.cs b/test/System.Web.Http.Test/Routing/UriPathExtensionMappingTests.cs index 89f3c4a56..1ef7bbaeb 100644 --- a/test/System.Web.Http.Test/Routing/UriPathExtensionMappingTests.cs +++ b/test/System.Web.Http.Test/Routing/UriPathExtensionMappingTests.cs @@ -3,7 +3,6 @@ using System.Net.Http.Formatting.DataSets; using System.Net.Http.Headers; -using System.Web.Http.Hosting; using System.Web.Http.Routing; using Microsoft.TestCommon; using Moq; @@ -85,6 +84,7 @@ public void ConstructorMediaTypeHeaderValue_ThrowsWithEmptyMediaType(string uriP typeof(HttpTestData), "UriTestDataStrings")] public void TryMatchMediaType_Returns_MatchWithExtensionInRouteData(string uriPathExtension, string mediaType, string baseUriString) { + GC.KeepAlive(baseUriString); // Mark parameter as used. See xUnit1026, [Theory] method doesn't use all parameters. UriPathExtensionMapping mapping = new UriPathExtensionMapping(uriPathExtension, mediaType); HttpRequestMessage request = GetRequestWithExtInRouteData(uriPathExtension); Assert.Equal(1.0, mapping.TryMatchMediaType(request)); @@ -97,6 +97,7 @@ public void TryMatchMediaType_Returns_MatchWithExtensionInRouteData(string uriPa typeof(HttpTestData), "UriTestDataStrings")] public void TryMatchMediaType_Returns_MatchWithExtensionInRouteData_DifferCase(string uriPathExtension, string mediaType, string baseUriString) { + GC.KeepAlive(baseUriString); // Mark parameter as used. See xUnit1026, [Theory] method doesn't use all parameters. UriPathExtensionMapping mapping = new UriPathExtensionMapping(uriPathExtension.ToUpperInvariant(), mediaType); HttpRequestMessage request = GetRequestWithExtInRouteData(uriPathExtension.ToLowerInvariant()); Assert.Equal(1.0, mapping.TryMatchMediaType(request)); diff --git a/test/System.Web.Http.Test/Services/DefaultServicesTests.cs b/test/System.Web.Http.Test/Services/DefaultServicesTests.cs index 7d89b1103..5b6ba0cb7 100644 --- a/test/System.Web.Http.Test/Services/DefaultServicesTests.cs +++ b/test/System.Web.Http.Test/Services/DefaultServicesTests.cs @@ -91,7 +91,7 @@ public void Constructor_DefaultServicesInContainer() Assert.IsType(valueProviderFactories[1]); object[] exceptionLoggers = defaultServices.GetServices(typeof(IExceptionLogger)).ToArray(); - Assert.Equal(0, exceptionLoggers.Length); + Assert.Empty(exceptionLoggers); } // Add tests diff --git a/test/System.Web.Http.Test/Services/ServicesExtensionsTests.cs b/test/System.Web.Http.Test/Services/ServicesExtensionsTests.cs index 7a3153f44..38317e4eb 100644 --- a/test/System.Web.Http.Test/Services/ServicesExtensionsTests.cs +++ b/test/System.Web.Http.Test/Services/ServicesExtensionsTests.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.Collections.Generic; -using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.ExceptionHandling; using Microsoft.TestCommon; @@ -34,7 +33,7 @@ public void GetExceptionHandler_DelegatesToGetService() // Act IExceptionHandler exceptionHandler = ServicesExtensions.GetExceptionHandler(services); - + // Assert mock.Verify(s => s.GetService(typeof(IExceptionHandler)), Times.Once()); Assert.Same(expectedExceptionHandler, exceptionHandler); @@ -58,8 +57,8 @@ public void GetExceptionLoggers_DelegatesToGetServices() // Assert mock.Verify(s => s.GetServices(typeof(IExceptionLogger)), Times.Once()); Assert.NotNull(exceptionLoggers); - Assert.Equal(1, exceptionLoggers.Count()); - Assert.Same(expectedExceptionLogger, exceptionLoggers.Single()); + IExceptionLogger exceptionLogger = Assert.Single(exceptionLoggers); + Assert.Same(expectedExceptionLogger, exceptionLogger); } } } diff --git a/test/System.Web.Http.Test/System.Web.Http.Test.csproj b/test/System.Web.Http.Test/System.Web.Http.Test.csproj index 552589bfa..dbda0c5e4 100644 --- a/test/System.Web.Http.Test/System.Web.Http.Test.csproj +++ b/test/System.Web.Http.Test/System.Web.Http.Test.csproj @@ -1,6 +1,7 @@  - + + {7F2C796F-43B2-4F8F-ABFF-A154EC8AAFA1} @@ -14,17 +15,17 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True - - False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + True @@ -39,19 +40,19 @@ - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -403,11 +404,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Test/Tracing/FormattingUtilitiesTest.cs b/test/System.Web.Http.Test/Tracing/FormattingUtilitiesTest.cs index 8445be206..57eba8b25 100644 --- a/test/System.Web.Http.Test/Tracing/FormattingUtilitiesTest.cs +++ b/test/System.Web.Http.Test/Tracing/FormattingUtilitiesTest.cs @@ -24,6 +24,7 @@ public class FormattingUtilitiesTest public void ValueToString_Formats(Type variationType, object testData) { // Arrange + GC.KeepAlive(variationType); // Mark parameter as used. See xUnit1026, [Theory] method doesn't use all parameters. string expected = Convert.ToString(testData, CultureInfo.CurrentCulture); // Act diff --git a/test/System.Web.Http.Test/Tracing/TracerCorrectnessTest.cs b/test/System.Web.Http.Test/Tracing/TracerCorrectnessTest.cs index ddaf39c7c..b3d9977a4 100644 --- a/test/System.Web.Http.Test/Tracing/TracerCorrectnessTest.cs +++ b/test/System.Web.Http.Test/Tracing/TracerCorrectnessTest.cs @@ -41,13 +41,13 @@ public static TheoryDataSet AllKnownTracers { typeof(IAuthorizationFilter), typeof(AuthorizationFilterTracer), new string[0] }, { typeof(IAuthenticationFilter), typeof(AuthenticationFilterTracer), new string[0] }, { typeof(IOverrideFilter), typeof(OverrideFilterTracer), new string[0] }, - { typeof(BufferedMediaTypeFormatter), typeof(BufferedMediaTypeFormatterTracer), new string[] + { typeof(BufferedMediaTypeFormatter), typeof(BufferedMediaTypeFormatterTracer), new string[] { // Values copied in ctor - "get_BufferSize", "set_BufferSize", - "get_SupportedMediaTypes", - "get_SupportedEncodings", - "get_MediaTypeMappings", + "get_BufferSize", "set_BufferSize", + "get_SupportedMediaTypes", + "get_SupportedEncodings", + "get_MediaTypeMappings", "get_RequiredMemberSelector", "set_RequiredMemberSelector", // Cannot override, inner handles correctly "ReadFromStreamAsync", "WriteToStreamAsync", "SelectCharacterEncoding" @@ -60,22 +60,22 @@ public static TheoryDataSet AllKnownTracers { typeof(FormatterParameterBinding), typeof(FormatterParameterBindingTracer), new string[] { // Handled in base ctor - "get_Formatters", "set_Formatters", - "get_BodyModelValidator", "set_BodyModelValidator", + "get_Formatters", "set_Formatters", + "get_BodyModelValidator", "set_BodyModelValidator", "get_Descriptor", // Cannot override but handled by overriding ErrorMessage "get_IsValid", "GetValue", "SetValue" } }, - { typeof(FormUrlEncodedMediaTypeFormatter), typeof(FormUrlEncodedMediaTypeFormatterTracer), new string[] + { typeof(FormUrlEncodedMediaTypeFormatter), typeof(FormUrlEncodedMediaTypeFormatterTracer), new string[] { // Values copied in ctor - "get_MaxDepth", "set_MaxDepth", + "get_MaxDepth", "set_MaxDepth", "get_ReadBufferSize", "set_ReadBufferSize", - "get_SupportedMediaTypes", - "get_SupportedEncodings", - "get_MediaTypeMappings", + "get_SupportedMediaTypes", + "get_SupportedEncodings", + "get_MediaTypeMappings", "get_RequiredMemberSelector", "set_RequiredMemberSelector", // Cannot override, base handles correctly via SupportedEncodings "SelectCharacterEncoding", @@ -84,14 +84,14 @@ public static TheoryDataSet AllKnownTracers { typeof(HttpActionBinding), typeof(HttpActionBindingTracer), new string[] { // Values copied in ctor - "get_ActionDescriptor", "set_ActionDescriptor", + "get_ActionDescriptor", "set_ActionDescriptor", "get_ParameterBindings", "set_ParameterBindings" } }, { typeof(HttpActionDescriptor), typeof(HttpActionDescriptorTracer), new string[] { // Values copied in ctor - "get_Configuration", "set_Configuration", + "get_Configuration", "set_Configuration", "get_ControllerDescriptor", "set_ControllerDescriptor" } }, @@ -102,7 +102,7 @@ public static TheoryDataSet AllKnownTracers { typeof(HttpControllerDescriptor), typeof(HttpControllerDescriptorTracer), new string[] { // Values copied in ctor - "get_Configuration", "set_Configuration", + "get_Configuration", "set_Configuration", "get_ControllerType", "set_ControllerType", "get_ControllerName", "set_ControllerName" } @@ -118,28 +118,28 @@ public static TheoryDataSet AllKnownTracers "GetValue", "SetValue", } }, - { typeof(JsonMediaTypeFormatter), typeof(JsonMediaTypeFormatterTracer), new string[] + { typeof(JsonMediaTypeFormatter), typeof(JsonMediaTypeFormatterTracer), new string[] { // Values copied in ctor "get_MaxDepth", "set_MaxDepth", - "get_SupportedMediaTypes", - "get_SupportedEncodings", - "get_MediaTypeMappings", + "get_SupportedMediaTypes", + "get_SupportedEncodings", + "get_MediaTypeMappings", "get_RequiredMemberSelector", "set_RequiredMemberSelector", "get_Indent", "set_Indent", "get_UseDataContractJsonSerializer", "set_UseDataContractJsonSerializer", "get_SerializerSettings", "set_SerializerSettings", // Cannot override, base handles correctly - "SelectCharacterEncoding", + "SelectCharacterEncoding", // Cannot override behavior, but copying SerializerSettings in ctor captures inner's result "CreateDefaultSerializerSettings" } }, - { typeof(MediaTypeFormatter), typeof(MediaTypeFormatterTracer), new string[] + { typeof(MediaTypeFormatter), typeof(MediaTypeFormatterTracer), new string[] { // Values copied in ctor - "get_SupportedMediaTypes", "get_SupportedEncodings", - "get_MediaTypeMappings", + "get_SupportedMediaTypes", "get_SupportedEncodings", + "get_MediaTypeMappings", "get_RequiredMemberSelector", "set_RequiredMemberSelector", // Cannot override, base handles correctly "SelectCharacterEncoding" @@ -161,18 +161,18 @@ public static TheoryDataSet AllKnownTracers "Dispose" } }, - { typeof(XmlMediaTypeFormatter), typeof(XmlMediaTypeFormatterTracer), new string[] + { typeof(XmlMediaTypeFormatter), typeof(XmlMediaTypeFormatterTracer), new string[] { // Values copied in ctor - "get_SupportedMediaTypes", - "get_SupportedEncodings", - "get_MediaTypeMappings", + "get_SupportedMediaTypes", + "get_SupportedEncodings", + "get_MediaTypeMappings", "get_RequiredMemberSelector", "set_RequiredMemberSelector", "get_UseXmlSerializer", "set_UseXmlSerializer", "get_Indent", "set_Indent", "get_WriterSettings", "get_MaxDepth", "set_MaxDepth", - "InvokeCreateXmlReader", "InvokeCreateXmlWriter", + "InvokeCreateXmlReader", "InvokeCreateXmlWriter", "InvokeGetDeserializer", "InvokeGetSerializer", // Cannot override, base handles correctly "SelectCharacterEncoding", @@ -187,6 +187,49 @@ public static TheoryDataSet AllKnownTracers } } + // Following filters work best if there are no duplicate tracer types in AllKnownTracers. Currently the case. + public static TheoryDataSet AllKnownTracers_NoExclusions + { + get + { + var dataSet = new TheoryDataSet(); + foreach (var item in AllKnownTracers) + { + dataSet.Add((Type)item[0], (Type)item[1]); + } + + return dataSet; + } + } + + public static TheoryDataSet AllKnownTracers_NoInnerType + { + get + { + var dataSet = new TheoryDataSet(); + foreach (var item in AllKnownTracers) + { + dataSet.Add((Type)item[1], (string[])item[2]); + } + + return dataSet; + } + } + + public static TheoryDataSet AllKnownTracers_JustTracerType + { + get + { + var dataSet = new TheoryDataSet(); + foreach (var item in AllKnownTracers) + { + dataSet.Add((Type)item[1]); + } + + return dataSet; + } + } + [Fact] public void All_Tracers_Are_Tested() { @@ -205,8 +248,8 @@ public void All_Tracers_Are_Tested() } [Theory] - [PropertyData("AllKnownTracers")] - public void All_Tracers_Are_Internal_And_Disposable_When_Inner_Is_Disposable(Type innerType, Type tracerType, string[] exclusions) + [PropertyData("AllKnownTracers_NoExclusions")] + public void All_Tracers_Are_Internal_And_Disposable_When_Inner_Is_Disposable(Type innerType, Type tracerType) { // Arrange TypeAssert.TypeProperties typeProperties = TypeAssert.TypeProperties.IsClass; @@ -224,16 +267,16 @@ public void All_Tracers_Are_Internal_And_Disposable_When_Inner_Is_Disposable(Typ } [Theory] - [PropertyData("AllKnownTracers")] - public void All_Tracers_Use_Correct_Namespace(Type innerType, Type tracerType, string[] exclusions) + [PropertyData("AllKnownTracers_JustTracerType")] + public void All_Tracers_Use_Correct_Namespace(Type tracerType) { // Arrange & Act & Assert Assert.Equal("System.Web.Http.Tracing.Tracers", tracerType.Namespace); } [Theory] - [PropertyData("AllKnownTracers")] - public void All_Excluded_Members_Are_Declared(Type innerType, Type tracerType, string[] exclusions) + [PropertyData("AllKnownTracers_NoInnerType")] + public void All_Excluded_Members_Are_Declared(Type tracerType, string[] exclusions) { // Arrange & Act string[] declaredMembers = tracerType.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(m => m.Name).ToArray(); diff --git a/test/System.Web.Http.Test/Tracing/Tracers/FilterTracerTest.cs b/test/System.Web.Http.Test/Tracing/Tracers/FilterTracerTest.cs index 5f61cdbdf..e4fb74230 100644 --- a/test/System.Web.Http.Test/Tracing/Tracers/FilterTracerTest.cs +++ b/test/System.Web.Http.Test/Tracing/Tracers/FilterTracerTest.cs @@ -23,11 +23,11 @@ public void CreateFilterTracers_IFilter_With_IFilter_Returns_Single_Wrapped_IFil Mock mockFilter = new Mock(); // Act - IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0]); + IFilter wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter); } [Fact] @@ -37,11 +37,11 @@ public void CreateFilterTracers_IFilter_With_IActionFilter_Returns_Single_Wrappe Mock mockFilter = new Mock(); // Act - IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0]); + IFilter wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter); } [Fact] @@ -51,11 +51,11 @@ public void CreateFilterTracers_IFilter_With_IExceptionFilter_Returns_Single_Wra Mock mockFilter = new Mock(); // Act - IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0]); + IFilter wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter); } [Fact] @@ -70,10 +70,8 @@ public void CreateFilterTracers_IFilter_With_IAuthenticationFilter_Returns_Singl // Assert Assert.NotNull(tracers); - Assert.Equal(1, tracers.Count()); - IFilter untypedFilter = tracers.Single(); - Assert.IsType(untypedFilter); - AuthenticationFilterTracer tracer = (AuthenticationFilterTracer)untypedFilter; + IFilter untypedFilter = Assert.Single(tracers); + AuthenticationFilterTracer tracer = Assert.IsType(untypedFilter); Assert.Same(expectedInner, tracer.InnerFilter); Assert.Same(expectedTraceWriter, tracer.TraceWriter); } @@ -85,11 +83,11 @@ public void CreateFilterTracers_IFilter_With_IAuthorizationFilter_Returns_Single Mock mockFilter = new Mock(); // Act - IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0]); + IFilter wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter); } [Fact] @@ -104,10 +102,8 @@ public void CreateFilterTracers_IFilter_With_IOverrideFilter_Returns_Single_Wrap // Assert Assert.NotNull(tracers); - Assert.Equal(1, tracers.Count()); - IFilter untypedFilter = tracers.Single(); - Assert.IsType(untypedFilter); - OverrideFilterTracer tracer = (OverrideFilterTracer)untypedFilter; + IFilter untypedFilter = Assert.Single(tracers); + OverrideFilterTracer tracer = Assert.IsType(untypedFilter); Assert.Same(expectedInner, tracer.InnerFilter); Assert.Same(expectedTraceWriter, tracer.TraceWriter); } @@ -119,11 +115,11 @@ public void CreateFilterTracers_IFilter_With_ActionFilterAttribute_Returns_Singl Mock mockFilter = new Mock(); // Act - IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0]); + IFilter wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter); } [Fact] @@ -133,11 +129,11 @@ public void CreateFilterTracers_IFilter_With_ExceptionFilterAttribute_Returns_Si Mock mockFilter = new Mock(); // Act - IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0]); + IFilter wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter); } [Fact] @@ -147,11 +143,11 @@ public void CreateFilterTracers_IFilter_With_AuthorizationFilterAttribute_Return Mock mockFilter = new Mock(); // Act - IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0]); + IFilter wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter); } [Fact] @@ -165,11 +161,11 @@ public void CreateFilterTracers_IFilter_With_All_Filter_Interfaces_Returns_Wrapp // Assert Assert.Equal(5, wrappedFilters.Length); - Assert.Equal(1, wrappedFilters.OfType().Count()); - Assert.Equal(1, wrappedFilters.OfType().Count()); - Assert.Equal(1, wrappedFilters.OfType().Count()); - Assert.Equal(1, wrappedFilters.OfType().Count()); - Assert.Equal(1, wrappedFilters.OfType().Count()); + Assert.Single(wrappedFilters.OfType()); + Assert.Single(wrappedFilters.OfType()); + Assert.Single(wrappedFilters.OfType()); + Assert.Single(wrappedFilters.OfType()); + Assert.Single(wrappedFilters.OfType()); } [Fact] @@ -180,11 +176,11 @@ public void CreateFilterTracers_With_IFilter_Returns_Single_Wrapped_IFilter() FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action); // Act - FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0].Instance); + FilterInfo wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter.Instance); } [Fact] @@ -195,11 +191,11 @@ public void CreateFilterTracers_With_IActionFilter_Returns_Single_Wrapped_IActio FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action); // Act - FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0].Instance); + FilterInfo wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter.Instance); } [Fact] @@ -210,11 +206,11 @@ public void CreateFilterTracers_With_IExceptionFilter_Returns_Single_Wrapped_IEx FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action); // Act - FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0].Instance); + FilterInfo wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter.Instance); } [Fact] @@ -230,12 +226,10 @@ public void CreateFilterTracers_With_IAuthenticationFilter_Returns_Single_Wrappe // Assert Assert.NotNull(filters); - Assert.Equal(1, filters.Count()); - FilterInfo filterInfo = filters.Single(); + FilterInfo filterInfo = Assert.Single(filters); Assert.NotNull(filterInfo); IFilter untypedFilter = filterInfo.Instance; - Assert.IsType(untypedFilter); - AuthenticationFilterTracer tracer = (AuthenticationFilterTracer)untypedFilter; + AuthenticationFilterTracer tracer = Assert.IsType(untypedFilter); Assert.Same(expectedInner, tracer.InnerFilter); Assert.Same(expectedTraceWriter, tracer.TraceWriter); } @@ -248,11 +242,11 @@ public void CreateFilterTracers_With_IAuthorizationFilter_Returns_Single_Wrapped FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action); // Act - FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0].Instance); + FilterInfo wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter.Instance); } [Fact] @@ -268,12 +262,10 @@ public void CreateFilterTracers_With_IOverrideFilter_Returns_Single_Wrapped_IOve // Assert Assert.NotNull(filters); - Assert.Equal(1, filters.Count()); - FilterInfo filterInfo = filters.Single(); + FilterInfo filterInfo = Assert.Single(filters); Assert.NotNull(filterInfo); IFilter untypedFilter = filterInfo.Instance; - Assert.IsType(untypedFilter); - OverrideFilterTracer tracer = (OverrideFilterTracer)untypedFilter; + OverrideFilterTracer tracer = Assert.IsType(untypedFilter); Assert.Same(expectedInner, tracer.InnerFilter); Assert.Same(expectedTraceWriter, tracer.TraceWriter); } @@ -286,11 +278,11 @@ public void CreateFilterTracers_With_ActionFilterAttribute_Returns_Single_Wrappe FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action); // Act - FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0].Instance); + FilterInfo wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter.Instance); } [Fact] @@ -301,11 +293,11 @@ public void CreateFilterTracers_With_ExceptionFilterAttribute_Returns_Single_Wra FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action); // Act - FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0].Instance); + FilterInfo wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter.Instance); } [Fact] @@ -316,11 +308,11 @@ public void CreateFilterTracers_With_AuthorizationFilterAttribute_Returns_Single FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action); // Act - FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray(); + IEnumerable wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()); // Assert - Assert.Equal(1, wrappedFilters.Length); - Assert.IsType(wrappedFilters[0].Instance); + FilterInfo wrappedFilter = Assert.Single(wrappedFilters); + Assert.IsType(wrappedFilter.Instance); } [Fact] @@ -334,11 +326,11 @@ public void CreateFilterTracers_With_All_Filter_Interfaces_Returns_Wrapped_Filte // Assert Assert.Equal(5, wrappedFilters.Length); - Assert.Equal(1, wrappedFilters.Where(f => f.Instance.GetType() == typeof(ActionFilterTracer)).Count()); - Assert.Equal(1, wrappedFilters.Where(f => f.Instance.GetType() == typeof(AuthorizationFilterTracer)).Count()); - Assert.Equal(1, wrappedFilters.Where(f => f.Instance.GetType() == typeof(AuthenticationFilterTracer)).Count()); - Assert.Equal(1, wrappedFilters.Where(f => f.Instance.GetType() == typeof(ExceptionFilterTracer)).Count()); - Assert.Equal(1, wrappedFilters.Where(f => f.Instance.GetType() == typeof(OverrideFilterTracer)).Count()); + Assert.Single(wrappedFilters, f => f.Instance.GetType() == typeof(ActionFilterTracer)); + Assert.Single(wrappedFilters, f => f.Instance.GetType() == typeof(AuthorizationFilterTracer)); + Assert.Single(wrappedFilters, f => f.Instance.GetType() == typeof(AuthenticationFilterTracer)); + Assert.Single(wrappedFilters, f => f.Instance.GetType() == typeof(ExceptionFilterTracer)); + Assert.Single(wrappedFilters, f => f.Instance.GetType() == typeof(OverrideFilterTracer)); } [Fact] diff --git a/test/System.Web.Http.Test/Tracing/Tracers/FormatterParameterBindingTracerTest.cs b/test/System.Web.Http.Test/Tracing/Tracers/FormatterParameterBindingTracerTest.cs index bcb9592be..326ac41ed 100644 --- a/test/System.Web.Http.Test/Tracing/Tracers/FormatterParameterBindingTracerTest.cs +++ b/test/System.Web.Http.Test/Tracing/Tracers/FormatterParameterBindingTracerTest.cs @@ -125,7 +125,7 @@ public async Task ExecuteBindingAsync_Traces_And_Invokes_Inner_ReadAsync() // Assert Assert.Equal(expectedTraces, traceWriter.Traces, new TraceRecordComparer()); - Assert.Equal("True", actionContext.ActionArguments["paramName"]); + Assert.Equal("true", actionContext.ActionArguments["paramName"]); } [Fact] diff --git a/test/System.Web.Http.Test/Tracing/Tracers/HttpParameterBindingTracerTest.cs b/test/System.Web.Http.Test/Tracing/Tracers/HttpParameterBindingTracerTest.cs index 2ae25288b..42e0b88fa 100644 --- a/test/System.Web.Http.Test/Tracing/Tracers/HttpParameterBindingTracerTest.cs +++ b/test/System.Web.Http.Test/Tracing/Tracers/HttpParameterBindingTracerTest.cs @@ -103,7 +103,7 @@ public void ValueProviderFactories_Returns_Empty_Enumerable_When_Not_IValueProvi ValueProviderFactory[] actualFactories = tracer.ValueProviderFactories.ToArray(); // Assert - Assert.Equal(0, actualFactories.Length); + Assert.Empty(actualFactories); } [Fact] diff --git a/test/System.Web.Http.Test/Validation/DefaultBodyModelValidatorTest.cs b/test/System.Web.Http.Test/Validation/DefaultBodyModelValidatorTest.cs index cc12b4a6f..6ec92a93f 100644 --- a/test/System.Web.Http.Test/Validation/DefaultBodyModelValidatorTest.cs +++ b/test/System.Web.Http.Test/Validation/DefaultBodyModelValidatorTest.cs @@ -100,7 +100,7 @@ public static IEnumerable ValidationErrors { "[0].Property3", "Error3" } } }, - + // Testing we don't blow up on cycles { LonelyPerson, typeof(Person), new Dictionary() { @@ -111,7 +111,7 @@ public static IEnumerable ValidationErrors // Testing that we don't bubble up exceptions when property getters throw { new Uri("/api/values", UriKind.Relative), typeof(Uri), new Dictionary() }, - + // Testing that excluded types don't result in any errors { typeof(string), typeof(Type), new Dictionary() }, { new byte[] { (byte)'a', (byte)'b' }, typeof(byte[]), new Dictionary() }, @@ -204,7 +204,7 @@ public void ExcludedPropertyTypes_AreShallowValidated() // Assert Assert.False(actionContext.ModelState.IsValid); ModelState modelState = actionContext.ModelState["Owner"]; - Assert.Equal(1, modelState.Errors.Count); + Assert.Single(modelState.Errors); } [Fact] diff --git a/test/System.Web.Http.Test/Validation/ModelStateFormatterLoggerTest.cs b/test/System.Web.Http.Test/Validation/ModelStateFormatterLoggerTest.cs index 85cf3ef99..da5db01a1 100644 --- a/test/System.Web.Http.Test/Validation/ModelStateFormatterLoggerTest.cs +++ b/test/System.Web.Http.Test/Validation/ModelStateFormatterLoggerTest.cs @@ -19,8 +19,8 @@ public void LogErrorAddsErrorToModelState() formatterLogger.LogError("property", "error"); Assert.True(modelState.ContainsKey("prefix.property")); - Assert.Equal(1, modelState["prefix.property"].Errors.Count); - Assert.Equal("error", modelState["prefix.property"].Errors[0].ErrorMessage); + ModelError error = Assert.Single(modelState["prefix.property"].Errors); + Assert.Equal("error", error.ErrorMessage); } [Fact] @@ -35,8 +35,8 @@ public void LogErrorAddsExceptionToModelState() formatterLogger.LogError("property", e); Assert.True(modelState.ContainsKey("prefix.property")); - Assert.Equal(1, modelState["prefix.property"].Errors.Count); - Assert.Equal(e, modelState["prefix.property"].Errors[0].Exception); + ModelError error = Assert.Single(modelState["prefix.property"].Errors); + Assert.Equal(e, error.Exception); } } } diff --git a/test/System.Web.Http.Test/Validation/Providers/AssociatedValidatorProviderTest.cs b/test/System.Web.Http.Test/Validation/Providers/AssociatedValidatorProviderTest.cs index eca579a08..f10eb34c4 100644 --- a/test/System.Web.Http.Test/Validation/Providers/AssociatedValidatorProviderTest.cs +++ b/test/System.Web.Http.Test/Validation/Providers/AssociatedValidatorProviderTest.cs @@ -49,7 +49,7 @@ public void GetValidatorsForPropertyWithLocalAttributes() // Assert provider.Verify(); - Assert.True(callbackAttributes.Any(a => a is RequiredAttribute)); + Assert.Contains(callbackAttributes, a => a is RequiredAttribute); } [Fact] @@ -69,7 +69,7 @@ public void GetValidatorsForPropertyWithMetadataAttributes() // Assert provider.Verify(); - Assert.True(callbackAttributes.Any(a => a is RangeAttribute)); + Assert.Contains(callbackAttributes, a => a is RangeAttribute); } [Fact] @@ -89,8 +89,8 @@ public void GetValidatorsForPropertyWithMixedAttributes() // Assert provider.Verify(); - Assert.True(callbackAttributes.Any(a => a is RangeAttribute)); - Assert.True(callbackAttributes.Any(a => a is RequiredAttribute)); + Assert.Contains(callbackAttributes, a => a is RangeAttribute); + Assert.Contains(callbackAttributes, a => a is RequiredAttribute); } [MetadataType(typeof(Metadata))] diff --git a/test/System.Web.Http.Test/Validation/Providers/InvalidModelValidatorProviderTest.cs b/test/System.Web.Http.Test/Validation/Providers/InvalidModelValidatorProviderTest.cs index 1d9405dc0..77a03c966 100644 --- a/test/System.Web.Http.Test/Validation/Providers/InvalidModelValidatorProviderTest.cs +++ b/test/System.Web.Http.Test/Validation/Providers/InvalidModelValidatorProviderTest.cs @@ -46,8 +46,8 @@ public void GetValidatorsReturnsInvalidModelValidatorsForInvalidModelProperty() IEnumerable validators = validatorProvider.GetValidators(_metadataProvider.GetMetadataForProperty(null, typeof(InvalidModel), "Value"), _noValidatorProviders); - Assert.Equal(1, validators.Count()); - Assert.Throws(() => validators.First().Validate(null, null), + ModelValidator validator = Assert.Single(validators); + Assert.Throws(() => validator.Validate(null, null), "Property 'Value' on type 'System.Web.Http.Validation.Providers.InvalidModelValidatorProviderTest+InvalidModel' is invalid. Value-typed properties marked as [Required] must also be marked with [DataMember(IsRequired=true)] to be recognized as required. Consider attributing the declaring type with [DataContract] and the property with [DataMember(IsRequired=true)]."); } diff --git a/test/System.Web.Http.Test/Validation/Validators/DataAnnotationsModelValidatorTest.cs b/test/System.Web.Http.Test/Validation/Validators/DataAnnotationsModelValidatorTest.cs index c22f97b3b..63c8f54a1 100644 --- a/test/System.Web.Http.Test/Validation/Validators/DataAnnotationsModelValidatorTest.cs +++ b/test/System.Web.Http.Test/Validation/Validators/DataAnnotationsModelValidatorTest.cs @@ -2,10 +2,12 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; +using System.Collections.Specialized; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web.Http.Metadata; using System.Web.Http.Metadata.Providers; +using System.Web.WebPages.TestUtils; using Microsoft.TestCommon; using Moq; using Moq.Protected; @@ -47,6 +49,90 @@ public void ValuesSet() Assert.Same(attribute, validator.Attribute); } + public static TheoryDataSet FalseAppSettingsData + { + get + { + return new TheoryDataSet + { + new NameValueCollection(), + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "false" }, + }, + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "False" }, + }, + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "false" }, + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "true" }, + }, + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "garbage" }, + }, + }; + } + } + + [Theory] + [PropertyData("FalseAppSettingsData")] + public void GetUseLegacyValidationMemberName_ReturnsFalse(NameValueCollection appSettings) + { + // Arrange & Act + var result = DataAnnotationsModelValidator.GetUseLegacyValidationMemberName(appSettings); + + // Assert + Assert.False(result); + } + + public static TheoryDataSet TrueAppSettingsData + { + get + { + return new TheoryDataSet + { + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "true" }, + }, + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "True" }, + }, + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "true" }, + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "false" }, + }, + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "true" }, + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "false" }, + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "garbage" }, + }, + new NameValueCollection + { + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "True" }, + { DataAnnotationsModelValidator.UseLegacyValidationMemberNameKey, "garbage" }, + }, + }; + } + } + + [Theory] + [PropertyData("TrueAppSettingsData")] + public void GetUseLegacyValidationMemberName_ReturnsTrue(NameValueCollection appSettings) + { + // Arrange & Act + var result = DataAnnotationsModelValidator.GetUseLegacyValidationMemberName(appSettings); + + // Assert + Assert.True(result); + } + public static TheoryDataSet ValidateSetsMemberNamePropertyDataSet { get @@ -57,10 +143,14 @@ public static TheoryDataSet ValidateSetsMemberNamePropert _metadataProvider.GetMetadataForProperty(() => 15, typeof(string), "Length"), "Length" }, + { + _metadataProvider.GetMetadataForProperty(() => string.Empty, typeof(AnnotatedModel), "Name"), + "Name" + }, { _metadataProvider.GetMetadataForType(() => new object(), typeof(SampleModel)), "SampleModel" - } + }, }; } } @@ -89,6 +179,123 @@ public void ValidateSetsMemberNamePropertyOfValidationContextForProperties(Model attribute.VerifyAll(); } + [Fact] + public void ValidateSetsMemberNameProperty_UsingDisplayName() + { + AppDomainUtils.RunInSeparateAppDomain(ValidateSetsMemberNameProperty_UsingDisplayName_Inner); + } + + private static void ValidateSetsMemberNameProperty_UsingDisplayName_Inner() + { + // Arrange + DataAnnotationsModelValidator.UseLegacyValidationMemberName = true; + var expectedMemberName = "Annotated Name"; + var attribute = new Mock { CallBase = true }; + attribute + .Protected() + .Setup("IsValid", ItExpr.IsAny(), ItExpr.IsAny()) + .Callback((object o, ValidationContext context) => + { + Assert.Equal(expectedMemberName, context.MemberName); + }) + .Returns(ValidationResult.Success) + .Verifiable(); + var validator = new DataAnnotationsModelValidator(_noValidatorProviders, attribute.Object); + var metadata = _metadataProvider.GetMetadataForProperty(() => string.Empty, typeof(AnnotatedModel), "Name"); + + // Act + var results = validator.Validate(metadata, container: null); + + // Assert + Assert.Empty(results); + attribute.VerifyAll(); + } + + // Confirm explicit false setting does not change Validate(...)'s behavior from its default. + [Fact] + public void ValidateSetsMemberNameProperty_NotUsingDisplayName() + { + AppDomainUtils.RunInSeparateAppDomain(ValidateSetsMemberNameProperty_NotUsingDisplayName_Inner); + } + + private static void ValidateSetsMemberNameProperty_NotUsingDisplayName_Inner() + { + // Arrange + DataAnnotationsModelValidator.UseLegacyValidationMemberName = false; + var expectedMemberName = "Name"; + var attribute = new Mock { CallBase = true }; + attribute + .Protected() + .Setup("IsValid", ItExpr.IsAny(), ItExpr.IsAny()) + .Callback((object o, ValidationContext context) => + { + Assert.Equal(expectedMemberName, context.MemberName); + }) + .Returns(ValidationResult.Success) + .Verifiable(); + var validator = new DataAnnotationsModelValidator(_noValidatorProviders, attribute.Object); + var metadata = _metadataProvider.GetMetadataForProperty(() => string.Empty, typeof(AnnotatedModel), "Name"); + + // Act + var results = validator.Validate(metadata, container: null); + + // Assert + Assert.Empty(results); + attribute.VerifyAll(); + } + + public static TheoryDataSet ValidateSetsDisplayNamePropertyDataSet + { + get + { + return new TheoryDataSet + { + { + _metadataProvider.GetMetadataForProperty(() => 15, typeof(string), "Length"), + "Length" + }, + { + _metadataProvider.GetMetadataForProperty(() => string.Empty, typeof(AnnotatedModel), "Name"), + "Annotated Name" + }, + { + _metadataProvider.GetMetadataForType(() => new object(), typeof(SampleModel)), + "SampleModel" + }, + }; + } + } + + [Theory] + [PropertyData("ValidateSetsDisplayNamePropertyDataSet")] + public void ValidateSetsDisplayNamePropertyOfValidationContextAsExpected( + ModelMetadata metadata, + string expectedDisplayName) + { + // Arrange + var attribute = new Mock + { + CallBase = true, + }; + attribute + .Protected() + .Setup("IsValid", ItExpr.IsAny(), ItExpr.IsAny()) + .Callback( + (object o, ValidationContext context) => Assert.Equal(expectedDisplayName, context.DisplayName)) + .Returns(ValidationResult.Success) + .Verifiable(); + DataAnnotationsModelValidator validator = new DataAnnotationsModelValidator( + _noValidatorProviders, + attribute.Object); + + // Act + IEnumerable results = validator.Validate(metadata, container: null); + + // Assert + Assert.Empty(results); + attribute.VerifyAll(); + } + [Fact] public void ValidateWithIsValidTrue() { @@ -222,5 +429,11 @@ class SampleModel { public string Name { get; set; } } + + private class AnnotatedModel + { + [Display(Name = "Annotated Name")] + public string Name { get; set; } + } } } diff --git a/test/System.Web.Http.Test/ValueProviders/Providers/QueryStringValueProviderTest.cs b/test/System.Web.Http.Test/ValueProviders/Providers/QueryStringValueProviderTest.cs index 85804eb43..ff1da55f5 100644 --- a/test/System.Web.Http.Test/ValueProviders/Providers/QueryStringValueProviderTest.cs +++ b/test/System.Web.Http.Test/ValueProviders/Providers/QueryStringValueProviderTest.cs @@ -28,7 +28,7 @@ public void ParseQueryString_Null() NameValueCollection result = ParseQueryString(null); // Assert - Assert.Equal(0, result.Count); + Assert.Empty(result); } [Fact] diff --git a/test/System.Web.Http.Test/packages.config b/test/System.Web.Http.Test/packages.config index 2dc840259..72e333be0 100644 --- a/test/System.Web.Http.Test/packages.config +++ b/test/System.Web.Http.Test/packages.config @@ -1,13 +1,14 @@  - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/test/System.Web.Http.Tracing.Test/System.Web.Http.Tracing.Test.csproj b/test/System.Web.Http.Tracing.Test/System.Web.Http.Tracing.Test.csproj index 528d0d7a2..ee60b9358 100644 --- a/test/System.Web.Http.Tracing.Test/System.Web.Http.Tracing.Test.csproj +++ b/test/System.Web.Http.Tracing.Test/System.Web.Http.Tracing.Test.csproj @@ -1,6 +1,7 @@  - + + {F87FD911-4A97-4057-8EAE-1CB96B9A1937} @@ -13,9 +14,9 @@ - - False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + True @@ -23,19 +24,19 @@ - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -67,14 +68,20 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + - - + diff --git a/test/System.Web.WebPages.Test/ApplicationParts/ApplicationPartRegistryTest.cs b/test/System.Web.WebPages.Test/ApplicationParts/ApplicationPartRegistryTest.cs index 8f39826e7..69bb91e0b 100644 --- a/test/System.Web.WebPages.Test/ApplicationParts/ApplicationPartRegistryTest.cs +++ b/test/System.Web.WebPages.Test/ApplicationParts/ApplicationPartRegistryTest.cs @@ -18,7 +18,7 @@ public void ApplicationModuleGeneratesRootRelativePaths() var root1 = "~/myappmodule"; var root2 = "~/myappmodule2/"; - // Act + // Act var actualPath11 = ApplicationPartRegistry.GetRootRelativeVirtualPath(root1, path1); var actualPath12 = ApplicationPartRegistry.GetRootRelativeVirtualPath(root1, path2); var actualPath21 = ApplicationPartRegistry.GetRootRelativeVirtualPath(root2, path1); @@ -114,7 +114,7 @@ public void RegisterCreatesRoutesForValidPages() // Assert Assert.True(dictionary.Exists("~/mymodule/Page1")); - Assert.Equal(dictionary.CreateInstance("~/mymodule/Page1"), "foo"); + Assert.Equal("foo", dictionary.CreateInstance("~/mymodule/Page1")); Assert.False(dictionary.Exists("~/mymodule/Page2")); Assert.False(dictionary.Exists("~/mymodule/Page3")); } diff --git a/test/System.Web.WebPages.Test/ApplicationParts/ApplicationPartTest.cs b/test/System.Web.WebPages.Test/ApplicationParts/ApplicationPartTest.cs index f26ff5d54..fa82487bd 100644 --- a/test/System.Web.WebPages.Test/ApplicationParts/ApplicationPartTest.cs +++ b/test/System.Web.WebPages.Test/ApplicationParts/ApplicationPartTest.cs @@ -30,7 +30,7 @@ public void ResolveVirtualPathResolvesRegularPathsUsingBaseVirtualPath() var virtualPath = ApplicationPart.ResolveVirtualPath(appPartRoot, basePath, path); // Assert - Assert.Equal(virtualPath, "~/base/somefile"); + Assert.Equal("~/base/somefile", virtualPath); } [Fact] @@ -45,7 +45,7 @@ public void ResolveVirtualPathResolvesAppRelativePathsUsingAppVirtualPath() var virtualPath = ApplicationPart.ResolveVirtualPath(appPartRoot, basePath, path); // Assert - Assert.Equal(virtualPath, "~/app/somefile"); + Assert.Equal("~/app/somefile", virtualPath); } [Fact] @@ -60,7 +60,7 @@ public void ResolveVirtualPathDoesNotAffectRootRelativePaths() var virtualPath = ApplicationPart.ResolveVirtualPath(appPartRoot, basePath, path); // Assert - Assert.Equal(virtualPath, "~/somefile"); + Assert.Equal("~/somefile", virtualPath); } [Fact] @@ -70,7 +70,7 @@ public void GetResourceNameFromVirtualPathForTopLevelPath() var moduleName = "my-module"; var path = "foo.baz"; - // Act + // Act var name = ApplicationPart.GetResourceNameFromVirtualPath(moduleName, path); // Assert @@ -84,11 +84,11 @@ public void GetResourceNameFromVirtualPathForItemInSubDir() var moduleName = "my-module"; var path = "/bar/foo"; - // Act + // Act var name = ApplicationPart.GetResourceNameFromVirtualPath(moduleName, path); // Assert - Assert.Equal(name, "my-module.bar.foo"); + Assert.Equal("my-module.bar.foo", name); } [Fact] @@ -98,11 +98,11 @@ public void GetResourceNameFromVirtualPathForItemWithSpaces() var moduleName = "my-module"; var path = "/program files/data files/my file .foo"; - // Act + // Act var name = ApplicationPart.GetResourceNameFromVirtualPath(moduleName, path); // Assert - Assert.Equal(name, "my-module.program_files.data_files.my file .foo"); + Assert.Equal("my-module.program_files.data_files.my file .foo", name); } [Fact] @@ -117,7 +117,7 @@ public void GetResourceVirtualPathForTopLevelItem() var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path); // Assert - Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + "foo.txt"); + Assert.Equal("~/r.ashx/" + moduleName + "/" + "foo.txt", virtualPath); } [Fact] @@ -132,7 +132,7 @@ public void GetResourceVirtualPathForTopLevelItemAndModuleRootWithTrailingSlash( var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path); // Assert - Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + "foo.txt"); + Assert.Equal("~/r.ashx/" + moduleName + "/" + "foo.txt", virtualPath); } [Fact] @@ -147,7 +147,7 @@ public void GetResourceVirtualPathForTopLevelItemAndNestedModuleRootPath() var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path); // Assert - Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + "foo.txt"); + Assert.Equal("~/r.ashx/" + moduleName + "/" + "foo.txt", virtualPath); } [Fact] @@ -162,7 +162,7 @@ public void GetResourceVirtualPathEncodesModuleName() var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path); // Assert - Assert.Equal(virtualPath, "~/r.ashx/" + "Debugger%20Package%20v?&%" + "/" + "foo.txt"); + Assert.Equal("~/r.ashx/" + "Debugger%20Package%20v?&%" + "/" + "foo.txt", virtualPath); } [Fact] @@ -178,7 +178,7 @@ public void GetResourceVirtualPathForNestedItemPath() var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path); // Assert - Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + itemPath); + Assert.Equal("~/r.ashx/" + moduleName + "/" + itemPath, virtualPath); } [Fact] @@ -194,7 +194,7 @@ public void GetResourceVirtualPathForItemPathWithParameters() var virtualPath = ApplicationPart.GetResourceVirtualPath(moduleName, moduleRoot, path); // Assert - Assert.Equal(virtualPath, "~/r.ashx/" + moduleName + "/" + itemPath); + Assert.Equal("~/r.ashx/" + moduleName + "/" + itemPath, virtualPath); } } } diff --git a/test/System.Web.WebPages.Test/ApplicationParts/ResourceHandlerTest.cs b/test/System.Web.WebPages.Test/ApplicationParts/ResourceHandlerTest.cs index bec2fb97c..c679afb29 100644 --- a/test/System.Web.WebPages.Test/ApplicationParts/ResourceHandlerTest.cs +++ b/test/System.Web.WebPages.Test/ApplicationParts/ResourceHandlerTest.cs @@ -29,7 +29,7 @@ public void ResourceHandlerWritesContentsOfFileToStream() // Assert response.Verify(); - Assert.Equal(Encoding.Default.GetString(stream.ToArray()), _fileContent); + Assert.Equal(_fileContent, Encoding.Default.GetString(stream.ToArray())); } [Fact] diff --git a/test/System.Web.WebPages.Test/Extensions/HttpResponseExtensionsTest.cs b/test/System.Web.WebPages.Test/Extensions/HttpResponseExtensionsTest.cs index f479afa59..c60f2ebb3 100644 --- a/test/System.Web.WebPages.Test/Extensions/HttpResponseExtensionsTest.cs +++ b/test/System.Web.WebPages.Test/Extensions/HttpResponseExtensionsTest.cs @@ -121,11 +121,11 @@ public void OutputCacheSetsVaryByValues() new[] { "baz", "baz2" }, HttpCacheability.Public); // Assert - Assert.Equal(varyByParams["foo"], true); - Assert.Equal(varyByHeader["bar"], true); - Assert.Equal(varyByHeader["bar2"], true); - Assert.Equal(varyByContentEncoding["baz"], true); - Assert.Equal(varyByContentEncoding["baz2"], true); + Assert.True(varyByParams["foo"]); + Assert.True(varyByHeader["bar"]); + Assert.True(varyByHeader["bar2"]); + Assert.True(varyByContentEncoding["baz"]); + Assert.True(varyByContentEncoding["baz2"]); } } } diff --git a/test/System.Web.WebPages.Test/Extensions/StringExtensionsTest.cs b/test/System.Web.WebPages.Test/Extensions/StringExtensionsTest.cs index e12a92b53..bb94690d5 100644 --- a/test/System.Web.WebPages.Test/Extensions/StringExtensionsTest.cs +++ b/test/System.Web.WebPages.Test/Extensions/StringExtensionsTest.cs @@ -85,14 +85,14 @@ public void AsDecimalUsesCurrentCulture() decimal value = 12345.00M; using (new CultureReplacer("ar-DZ")) { - Assert.Equal(value.ToString(CultureInfo.CurrentCulture), "12345.00"); - Assert.Equal(value.ToString(), "12345.00"); + Assert.Equal("12345.00", value.ToString(CultureInfo.CurrentCulture)); + Assert.Equal("12345.00", value.ToString()); } using (new CultureReplacer("bg-BG")) { - Assert.Equal(value.ToString(CultureInfo.CurrentCulture), "12345,00"); - Assert.Equal(value.ToString(), "12345,00"); + Assert.Equal("12345,00", value.ToString(CultureInfo.CurrentCulture)); + Assert.Equal("12345,00", value.ToString()); } } diff --git a/test/System.Web.WebPages.Test/Helpers/AntiXsrf/AntiForgeryTokenStoreTest.cs b/test/System.Web.WebPages.Test/Helpers/AntiXsrf/AntiForgeryTokenStoreTest.cs index 25e1860b9..7b2772a85 100644 --- a/test/System.Web.WebPages.Test/Helpers/AntiXsrf/AntiForgeryTokenStoreTest.cs +++ b/test/System.Web.WebPages.Test/Helpers/AntiXsrf/AntiForgeryTokenStoreTest.cs @@ -223,7 +223,7 @@ public void SaveCookieToken(bool requireSsl, bool? expectedCookieSecureFlag) tokenStore.SaveCookieToken(mockHttpContext.Object, token); // Assert - Assert.Equal(1, cookies.Count); + Assert.Single(cookies); HttpCookie cookie = cookies["cookie-name"]; Assert.NotNull(cookie); diff --git a/test/System.Web.WebPages.Test/Html/HtmlHelperTest.cs b/test/System.Web.WebPages.Test/Html/HtmlHelperTest.cs index 9fc5472b8..f9564992c 100644 --- a/test/System.Web.WebPages.Test/Html/HtmlHelperTest.cs +++ b/test/System.Web.WebPages.Test/Html/HtmlHelperTest.cs @@ -35,7 +35,7 @@ public void EncodeObject() string encodedHtml = htmlHelper.Encode(text); // Assert - Assert.Equal(encodedHtml, "<br />"); + Assert.Equal("<br />", encodedHtml); } [Fact] @@ -63,7 +63,7 @@ public void EncodeString() string encodedHtml = htmlHelper.Encode(text); // Assert - Assert.Equal(encodedHtml, "<br />"); + Assert.Equal("<br />", encodedHtml); } [Fact] @@ -201,7 +201,7 @@ private static object GetAttributes() /// has the attribute name underscore correctly transformed to a dash /// /// - public static void AssertHelperTransformsAttributesUnderscoresToDashs(Func helperInvocation) + internal static void AssertHelperTransformsAttributesUnderscoresToDashs(Func helperInvocation) { // Arrange HtmlHelper helper = HtmlHelperFactory.Create(); diff --git a/test/System.Web.WebPages.Test/ScopeStorage/ScopeStorageDictionaryTest.cs b/test/System.Web.WebPages.Test/ScopeStorage/ScopeStorageDictionaryTest.cs index 0f25fe4d5..8f727b14c 100644 --- a/test/System.Web.WebPages.Test/ScopeStorage/ScopeStorageDictionaryTest.cs +++ b/test/System.Web.WebPages.Test/ScopeStorage/ScopeStorageDictionaryTest.cs @@ -16,7 +16,7 @@ public void ScopeStorageDictionaryLooksUpLocalValuesFirst() var stateStorage = GetChainedStorageStateDictionary(); // Act and Assert - Assert.Equal(stateStorage["f"], "f2"); + Assert.Equal("f2", stateStorage["f"]); } [Fact] @@ -26,8 +26,8 @@ public void ScopeStorageDictionaryOverridesParentValuesWithLocalValues() var stateStorage = GetChainedStorageStateDictionary(); // Act and Assert - Assert.Equal(stateStorage["a"], "a2"); - Assert.Equal(stateStorage["d"], "d2"); + Assert.Equal("a2", stateStorage["a"]); + Assert.Equal("d2", stateStorage["d"]); } [Fact] @@ -37,8 +37,8 @@ public void ScopeStorageDictionaryLooksUpParentValuesWhenNotFoundLocally() var stateStorage = GetChainedStorageStateDictionary(); // Act and Assert - Assert.Equal(stateStorage["c"], "c0"); - Assert.Equal(stateStorage["b"], "b1"); + Assert.Equal("c0", stateStorage["c"]); + Assert.Equal("b1", stateStorage["b"]); } [Fact] @@ -99,12 +99,12 @@ public void ScopeStorageDictionaryGetsValuesFromCurrentAndBaseScope() var scopeStorage = GetChainedStorageStateDictionary(); // Act and Assert - Assert.Equal(scopeStorage["a"], "a2"); - Assert.Equal(scopeStorage["b"], "b1"); - Assert.Equal(scopeStorage["c"], "c0"); - Assert.Equal(scopeStorage["d"], "d2"); - Assert.Equal(scopeStorage["e"], "e1"); - Assert.Equal(scopeStorage["f"], "f2"); + Assert.Equal("a2", scopeStorage["a"]); + Assert.Equal("b1", scopeStorage["b"]); + Assert.Equal("c0", scopeStorage["c"]); + Assert.Equal("d2", scopeStorage["d"]); + Assert.Equal("e1", scopeStorage["e"]); + Assert.Equal("f2", scopeStorage["f"]); } [Fact] @@ -117,7 +117,7 @@ public void ClearRemovesAllItemsFromCurrentScope() dictionary.Clear(); // Assert - Assert.Equal(0, dictionary.Count); + Assert.Empty(dictionary); } [Fact] @@ -137,16 +137,16 @@ public void CopyToCopiesItemsToArrayAtSpecifiedIndex() var dictionary = GetChainedStorageStateDictionary(); var array = new KeyValuePair[8]; - // Act + // Act dictionary.CopyTo(array, 2); // Assert - Assert.Equal(array[2].Key, "a"); - Assert.Equal(array[2].Value, "a2"); - Assert.Equal(array[4].Key, "f"); - Assert.Equal(array[4].Value, "f2"); - Assert.Equal(array[7].Key, "c"); - Assert.Equal(array[7].Value, "c0"); + Assert.Equal("a", array[2].Key); + Assert.Equal("a2", array[2].Value); + Assert.Equal("f", array[4].Key); + Assert.Equal("f2", array[4].Value); + Assert.Equal("c", array[7].Key); + Assert.Equal("c0", array[7].Value); } private ScopeStorageDictionary GetChainedStorageStateDictionary() diff --git a/test/System.Web.WebPages.Test/ScopeStorage/ScopeStorageKeyComparerTest.cs b/test/System.Web.WebPages.Test/ScopeStorage/ScopeStorageKeyComparerTest.cs index fcd226196..c4e3f80eb 100644 --- a/test/System.Web.WebPages.Test/ScopeStorage/ScopeStorageKeyComparerTest.cs +++ b/test/System.Web.WebPages.Test/ScopeStorage/ScopeStorageKeyComparerTest.cs @@ -16,7 +16,7 @@ public void ScopeStorageComparerPerformsCaseInsensitiveOrdinalComparisonForStrin var dictionary = new Dictionary(ScopeStorageComparer.Instance) { { "foo", "bar" } }; // Act and Assert - Assert.Equal(dictionary["foo"], "bar"); + Assert.Equal("bar", dictionary["foo"]); Assert.Equal(dictionary["foo"], dictionary["FOo"]); } @@ -27,9 +27,9 @@ public void ScopeStorageComparerPerformsRegularComparisonForOtherTypes() var stateStorage = new Dictionary { { 4, "4-value" }, { new Person { ID = 10 }, "person-value" } }; // Act and Assert - Assert.Equal(stateStorage[4], "4-value"); + Assert.Equal("4-value", stateStorage[4]); Assert.Equal(stateStorage[(int)8 / 2], stateStorage[4]); - Assert.Equal(stateStorage[new Person { ID = 10 }], "person-value"); + Assert.Equal("person-value", stateStorage[new Person { ID = 10 }]); } private class Person diff --git a/test/System.Web.WebPages.Test/ScopeStorage/WebConfigScopeStorageTest.cs b/test/System.Web.WebPages.Test/ScopeStorage/WebConfigScopeStorageTest.cs index b7d0f8221..bcb4a6b49 100644 --- a/test/System.Web.WebPages.Test/ScopeStorage/WebConfigScopeStorageTest.cs +++ b/test/System.Web.WebPages.Test/ScopeStorage/WebConfigScopeStorageTest.cs @@ -20,8 +20,8 @@ public void WebConfigScopeStorageReturnsConfigValue() var stateStorage = GetWebConfigScopeStorage(); // Assert - Assert.Equal(stateStorage["foo1"], "bar1"); - Assert.Equal(stateStorage["foo2"], "bar2"); + Assert.Equal("bar1", stateStorage["foo1"]); + Assert.Equal("bar2", stateStorage["foo2"]); } [Fact] @@ -31,8 +31,8 @@ public void WebConfigScopeStoragePerformsCaseInsensitiveKeyCompares() var stateStorage = GetWebConfigScopeStorage(); // Assert - Assert.Equal(stateStorage["FOO1"], "bar1"); - Assert.Equal(stateStorage["FoO2"], "bar2"); + Assert.Equal("bar1", stateStorage["FOO1"]); + Assert.Equal("bar2", stateStorage["FoO2"]); } [Fact] diff --git a/test/System.Web.WebPages.Test/System.Web.WebPages.Test.csproj b/test/System.Web.WebPages.Test/System.Web.WebPages.Test.csproj index 1f83aca5c..fca409a32 100644 --- a/test/System.Web.WebPages.Test/System.Web.WebPages.Test.csproj +++ b/test/System.Web.WebPages.Test/System.Web.WebPages.Test.csproj @@ -1,6 +1,7 @@  - + + {0F4870DB-A799-4DBA-99DF-0D74BB52FEC2} @@ -13,36 +14,36 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll - True + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll + 3.5 - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -181,11 +182,17 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + + \ No newline at end of file diff --git a/test/System.Web.WebPages.Test/Utils/CultureUtilTest.cs b/test/System.Web.WebPages.Test/Utils/CultureUtilTest.cs index 71bbbfc51..def906570 100644 --- a/test/System.Web.WebPages.Test/Utils/CultureUtilTest.cs +++ b/test/System.Web.WebPages.Test/Utils/CultureUtilTest.cs @@ -13,11 +13,12 @@ namespace System.Web.WebPages.Test public class CultureUtilTest { [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoCultureWithNoUserLanguagesDoesNothing() { // Arrange var context = GetContextForSetCulture(null); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; CultureInfo culture = thread.CurrentCulture; // Act @@ -28,11 +29,12 @@ public void SetAutoCultureWithNoUserLanguagesDoesNothing() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoUICultureWithNoUserLanguagesDoesNothing() { // Arrange var context = GetContextForSetCulture(null); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; CultureInfo culture = thread.CurrentUICulture; // Act @@ -43,11 +45,12 @@ public void SetAutoUICultureWithNoUserLanguagesDoesNothing() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoCultureWithEmptyUserLanguagesDoesNothing() { // Arrange var context = GetContextForSetCulture(Enumerable.Empty()); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; CultureInfo culture = thread.CurrentCulture; // Act @@ -58,11 +61,12 @@ public void SetAutoCultureWithEmptyUserLanguagesDoesNothing() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoUICultureWithEmptyUserLanguagesDoesNothing() { // Arrange var context = GetContextForSetCulture(Enumerable.Empty()); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; CultureInfo culture = thread.CurrentUICulture; // Act @@ -73,11 +77,12 @@ public void SetAutoUICultureWithEmptyUserLanguagesDoesNothing() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoCultureWithBlankUserLanguagesDoesNothing() { // Arrange var context = GetContextForSetCulture(new[] { " " }); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; CultureInfo culture = thread.CurrentCulture; // Act @@ -88,11 +93,12 @@ public void SetAutoCultureWithBlankUserLanguagesDoesNothing() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoUICultureWithBlankUserLanguagesDoesNothing() { // Arrange var context = GetContextForSetCulture(new[] { " " }); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; CultureInfo culture = thread.CurrentUICulture; // Act @@ -103,12 +109,13 @@ public void SetAutoUICultureWithBlankUserLanguagesDoesNothing() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoCultureWithInvalidLanguageDoesNothing() { // Arrange // "sans-culture" is an invalid culture name everywhere -- even on Windows 10. var context = GetContextForSetCulture(new[] { "sans-culture", "bb-BB", "cc-CC" }); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; CultureInfo culture = thread.CurrentCulture; // Act @@ -119,12 +126,13 @@ public void SetAutoCultureWithInvalidLanguageDoesNothing() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoUICultureWithInvalidLanguageDoesNothing() { // Arrange // "sans-culture" is an invalid culture name everywhere -- even on Windows 10. var context = GetContextForSetCulture(new[] { "sans-culture", "bb-BB", "cc-CC" }); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; CultureInfo culture = thread.CurrentUICulture; // Act @@ -135,11 +143,12 @@ public void SetAutoUICultureWithInvalidLanguageDoesNothing() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoCultureDetectsUserLanguageCulture() { // Arrange var context = GetContextForSetCulture(new[] { "en-GB", "en-US", "ar-eg" }); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; // Act CultureUtil.SetCulture(thread, context, "auto"); @@ -150,11 +159,12 @@ public void SetAutoCultureDetectsUserLanguageCulture() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoUICultureDetectsUserLanguageCulture() { // Arrange var context = GetContextForSetCulture(new[] { "en-GB", "en-US", "ar-eg" }); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; // Act CultureUtil.SetUICulture(thread, context, "auto"); @@ -165,11 +175,12 @@ public void SetAutoUICultureDetectsUserLanguageCulture() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoCultureUserLanguageWithQParameterCulture() { // Arrange var context = GetContextForSetCulture(new[] { "en-GB;q=0.3", "en-US", "ar-eg;q=0.5" }); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; // Act CultureUtil.SetCulture(thread, context, "auto"); @@ -180,11 +191,12 @@ public void SetAutoCultureUserLanguageWithQParameterCulture() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetAutoUICultureDetectsUserLanguageWithQParameterCulture() { // Arrange var context = GetContextForSetCulture(new[] { "en-GB;q=0.3", "en-US", "ar-eg;q=0.5" }); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; // Act CultureUtil.SetUICulture(thread, context, "auto"); @@ -195,33 +207,36 @@ public void SetAutoUICultureDetectsUserLanguageWithQParameterCulture() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetCultureWithInvalidCultureThrows() { // Arrange var context = GetContextForSetCulture(); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; // Act and Assert Assert.Throws(() => CultureUtil.SetCulture(thread, context, "sans-culture")); } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetUICultureWithInvalidCultureThrows() { // Arrange var context = GetContextForSetCulture(); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; // Act and Assert Assert.Throws(() => CultureUtil.SetUICulture(thread, context, "sans-culture")); } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetCultureWithValidCulture() { // Arrange var context = GetContextForSetCulture(); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; // Act CultureUtil.SetCulture(thread, context, "en-GB"); @@ -232,11 +247,12 @@ public void SetCultureWithValidCulture() } [Fact] + [ReplaceCulture(Culture = "es-PR", UICulture = "es-PR")] public void SetUICultureWithValidCulture() { // Arrange var context = GetContextForSetCulture(); - Thread thread = GetThread(); + Thread thread = Thread.CurrentThread; // Act CultureUtil.SetUICulture(thread, context, "en-GB"); @@ -246,11 +262,6 @@ public void SetUICultureWithValidCulture() Assert.Equal("05/01/1979", new DateTime(1979, 1, 5).ToString("d", thread.CurrentUICulture)); } - private static Thread GetThread() - { - return new Thread(() => { }); - } - private static HttpContextBase GetContextForSetCulture(IEnumerable userLanguages = null) { Mock contextMock = new Mock(); diff --git a/test/System.Web.WebPages.Test/Utils/HtmlAttributePropertyHelperTest.cs b/test/System.Web.WebPages.Test/Utils/HtmlAttributePropertyHelperTest.cs index ea4cd4377..cbc209fd3 100644 --- a/test/System.Web.WebPages.Test/Utils/HtmlAttributePropertyHelperTest.cs +++ b/test/System.Web.WebPages.Test/Utils/HtmlAttributePropertyHelperTest.cs @@ -80,7 +80,7 @@ public void HtmlAttributePropertyHelperReturnsCachedPropertyHelper() PropertyHelper[] helpers2 = HtmlAttributePropertyHelper.GetProperties(anonymous); // Assert - Assert.Equal(1, helpers1.Length); + Assert.Single(helpers1); Assert.ReferenceEquals(helpers1, helpers2); Assert.ReferenceEquals(helpers1[0], helpers2[0]); } @@ -96,17 +96,17 @@ public void HtmlAttributeDoesNotShareCacheWithPropertyHelper() PropertyHelper[] helpers2 = PropertyHelper.GetProperties(anonymous); // Assert - Assert.Equal(1, helpers1.Length); - Assert.Equal(1, helpers2.Length); + PropertyHelper helper1 = Assert.Single(helpers1); + PropertyHelper helper2 = Assert.Single(helpers2); - Assert.NotEqual(helpers1, helpers2); - Assert.NotEqual(helpers1[0], helpers2[0]); + Assert.NotEqual(helpers1, helpers2); + Assert.NotEqual(helper1, helper2); - Assert.IsType(helpers1[0]); - Assert.IsNotType(helpers2[0]); + Assert.IsType(helper1); + Assert.IsNotType(helper2); - Assert.Equal("bar-baz1", helpers1[0].Name); - Assert.Equal("bar_baz1", helpers2[0].Name); + Assert.Equal("bar-baz1", helper1.Name); + Assert.Equal("bar_baz1", helper2.Name); } } } diff --git a/test/System.Web.WebPages.Test/Utils/PathUtilTest.cs b/test/System.Web.WebPages.Test/Utils/PathUtilTest.cs index c482d9746..9af187811 100644 --- a/test/System.Web.WebPages.Test/Utils/PathUtilTest.cs +++ b/test/System.Web.WebPages.Test/Utils/PathUtilTest.cs @@ -57,7 +57,7 @@ public void GetExtensionReturnsEmptyStringForPathsThatDoNotContainExtension() var extensions = paths.Select(PathUtil.GetExtension); // Assert - Assert.True(extensions.All(ext => ext.Length == 0)); + Assert.All(extensions, ext => Assert.Empty(ext)); } [Fact] @@ -70,7 +70,7 @@ public void GetExtensionReturnsEmptyStringForPathsContainingPathInfo() var extensions = paths.Select(PathUtil.GetExtension); // Assert - Assert.True(extensions.All(ext => ext.Length == 0)); + Assert.All(extensions, ext => Assert.Empty(ext)); } [Fact] @@ -83,7 +83,7 @@ public void GetExtensionReturnsEmptyStringForPathsTerminatingWithADot() var extensions = paths.Select(PathUtil.GetExtension); // Assert - Assert.True(extensions.All(ext => ext.Length == 0)); + Assert.All(extensions, ext => Assert.Empty(ext)); } [Fact] @@ -98,8 +98,8 @@ public void GetExtensionReturnsExtensionsForPathsTerminatingInExtension() string ext2 = PathUtil.GetExtension(path2); // Assert - Assert.Equal(ext1, ".cshtml"); - Assert.Equal(ext2, ".txt"); + Assert.Equal(".cshtml", ext1); + Assert.Equal(".txt", ext2); } [Fact] diff --git a/test/System.Web.WebPages.Test/Utils/PropertyHelperTest.cs b/test/System.Web.WebPages.Test/Utils/PropertyHelperTest.cs index 36394375b..4c8c619dc 100644 --- a/test/System.Web.WebPages.Test/Utils/PropertyHelperTest.cs +++ b/test/System.Web.WebPages.Test/Utils/PropertyHelperTest.cs @@ -65,7 +65,7 @@ public void PropertyHelperReturnsCachedPropertyHelper() PropertyHelper[] helpers2 = PropertyHelper.GetProperties(anonymous); // Assert - Assert.Equal(1, helpers1.Length); + Assert.Single(helpers1); Assert.ReferenceEquals(helpers1, helpers2); Assert.ReferenceEquals(helpers1[0], helpers2[0]); } @@ -149,8 +149,8 @@ public void PropertyHelperWorksForStruct() anonymous.StringProp = "Five"; // Act + Assert - PropertyHelper helper1 = Assert.Single(PropertyHelper.GetProperties(anonymous).Where(prop => prop.Name == "IntProp")); - PropertyHelper helper2 = Assert.Single(PropertyHelper.GetProperties(anonymous).Where(prop => prop.Name == "StringProp")); + PropertyHelper helper1 = Assert.Single(PropertyHelper.GetProperties(anonymous), prop => prop.Name == "IntProp"); + PropertyHelper helper2 = Assert.Single(PropertyHelper.GetProperties(anonymous), prop => prop.Name == "StringProp"); Assert.Equal(3, helper1.GetValue(anonymous)); Assert.Equal("Five", helper2.GetValue(anonymous)); } @@ -196,8 +196,8 @@ public void PropertyHelperForDerivedClass() Assert.NotNull(helpers); Assert.Equal(2, helpers.Length); - PropertyHelper propAHelper = Assert.Single(helpers.Where(h => h.Name == "PropA")); - PropertyHelper propBHelper = Assert.Single(helpers.Where(h => h.Name == "PropB")); + PropertyHelper propAHelper = Assert.Single(helpers, h => h.Name == "PropA"); + PropertyHelper propBHelper = Assert.Single(helpers, h => h.Name == "PropB"); Assert.Equal("propAValue", propAHelper.GetValue(derived)); Assert.Equal("propBValue", propBHelper.GetValue(derived)); @@ -216,8 +216,8 @@ public void PropertyHelperForDerivedClassWithNew() Assert.NotNull(helpers); Assert.Equal(2, helpers.Length); - PropertyHelper propAHelper = Assert.Single(helpers.Where(h => h.Name == "PropA")); - PropertyHelper propBHelper = Assert.Single(helpers.Where(h => h.Name == "PropB")); + PropertyHelper propAHelper = Assert.Single(helpers, h => h.Name == "PropA"); + PropertyHelper propBHelper = Assert.Single(helpers, h => h.Name == "PropB"); Assert.Equal("propAValue", propAHelper.GetValue(derived)); Assert.Equal("Newed", propBHelper.GetValue(derived)); @@ -236,8 +236,8 @@ public void PropertyHelperForDerivedWithVirtual() Assert.NotNull(helpers); Assert.Equal(2, helpers.Length); - PropertyHelper propAHelper = Assert.Single(helpers.Where(h => h.Name == "PropA")); - PropertyHelper propBHelper = Assert.Single(helpers.Where(h => h.Name == "PropB")); + PropertyHelper propAHelper = Assert.Single(helpers, h => h.Name == "PropA"); + PropertyHelper propBHelper = Assert.Single(helpers, h => h.Name == "PropB"); Assert.Equal("Overriden", propAHelper.GetValue(derived)); Assert.Equal("propBValue", propBHelper.GetValue(derived)); diff --git a/test/System.Web.WebPages.Test/Validation/ValidationHelperTest.cs b/test/System.Web.WebPages.Test/Validation/ValidationHelperTest.cs index 57746c26c..a71025d17 100644 --- a/test/System.Web.WebPages.Test/Validation/ValidationHelperTest.cs +++ b/test/System.Web.WebPages.Test/Validation/ValidationHelperTest.cs @@ -19,8 +19,8 @@ public class ValidationHelperTest : IDisposable public void FormFieldKeyIsCommonToModelStateAndValidationHelper() { // Arrange + const string key = "_FORM"; RequestFieldValidatorBase.IgnoreUseUnvalidatedValues = true; - string key = "_FORM"; ValidationHelper validationHelper = GetValidationHelper(GetContext()); // Act and Assert @@ -75,8 +75,8 @@ public void RequiredReturnsErrorMessageIfFieldIsNotPresentInForm() var results = validationHelper.Validate(); // Assert - Assert.Equal(1, results.Count()); - Assert.Equal(message, results.First().ErrorMessage); + ValidationResult result = Assert.Single(results); + Assert.Equal(message, result.ErrorMessage); } [Fact] @@ -92,8 +92,8 @@ public void RequiredReturnsErrorMessageIfFieldIsEmpty() var results = validationHelper.Validate(); // Assert - Assert.Equal(1, results.Count()); - Assert.Equal(message, results.First().ErrorMessage); + ValidationResult result = Assert.Single(results); + Assert.Equal(message, result.ErrorMessage); } [Fact] @@ -109,7 +109,7 @@ public void RequiredReturnsNoValidationResultsIfFieldIsPresent() var results = validationHelper.Validate(); // Assert - Assert.Equal(0, results.Count()); + Assert.Empty(results); } [Fact] @@ -124,8 +124,8 @@ public void RequiredUsesDefaultErrorMessageIfNoValueIsProvided() var results = validationHelper.Validate(); // Assert - Assert.Equal(1, results.Count()); - Assert.Equal("This field is required.", results.First().ErrorMessage); + ValidationResult result = Assert.Single(results); + Assert.Equal("This field is required.", result.ErrorMessage); } [Fact] @@ -416,8 +416,7 @@ public void AddWorksForCustomValidator() var oddValidator = new Mock(); oddValidator.Setup(c => c.Validate(It.IsAny())).Returns(v => { - Assert.IsAssignableFrom(v.ObjectInstance); - var context = (HttpContextBase)v.ObjectInstance; + var context = Assert.IsAssignableFrom(v.ObjectInstance); var value = Int32.Parse(context.Request.Form["foo"]); if (value % 2 != 0) @@ -430,11 +429,11 @@ public void AddWorksForCustomValidator() // Act validationHelper.Add("foo", oddValidator.Object); - var result = validationHelper.Validate(); + var results = validationHelper.Validate(); // Assert - Assert.Equal(1, result.Count()); - Assert.Equal(message, result.First().ErrorMessage); + ValidationResult result = Assert.Single(results); + Assert.Equal(message, result.ErrorMessage); oddValidator.Verify(); } @@ -447,8 +446,7 @@ public void ValidateRunsForSpecifiedFields() var oddValidator = new Mock(); oddValidator.Setup(c => c.Validate(It.IsAny())).Returns(v => { - Assert.IsAssignableFrom(v.ObjectInstance); - var context = (HttpContextBase)v.ObjectInstance; + var context = Assert.IsAssignableFrom(v.ObjectInstance); if (context.Request.Form["foo"].IsEmpty()) { return ValidationResult.Success; @@ -465,11 +463,11 @@ public void ValidateRunsForSpecifiedFields() // Act validationHelper.Add(new[] { "foo", "bar" }, oddValidator.Object); validationHelper.RequireField("foo"); - var result = validationHelper.Validate("foo"); + var results = validationHelper.Validate("foo"); // Assert - Assert.Equal(1, result.Count()); - Assert.Equal("This field is required.", result.First().ErrorMessage); + ValidationResult result = Assert.Single(results); + Assert.Equal("This field is required.", result.ErrorMessage); } [Fact] @@ -481,8 +479,7 @@ public void GetErrorsReturnsAllErrorsIfNoParametersAreSpecified() var oddValidator = new Mock(); oddValidator.Setup(c => c.Validate(It.IsAny())).Returns(v => { - Assert.IsAssignableFrom(v.ObjectInstance); - var context = (HttpContextBase)v.ObjectInstance; + var context = Assert.IsAssignableFrom(v.ObjectInstance); if (context.Request.Form["foo"].IsEmpty()) { return ValidationResult.Success; @@ -516,8 +513,7 @@ public void IsValidReturnsTrueIfAllValuesPassValidation() var oddValidator = new Mock(); oddValidator.Setup(c => c.Validate(It.IsAny())).Returns(v => { - Assert.IsAssignableFrom(v.ObjectInstance); - var context = (HttpContextBase)v.ObjectInstance; + var context = Assert.IsAssignableFrom(v.ObjectInstance); if (context.Request.Form["foo"].IsEmpty()) { return ValidationResult.Success; @@ -549,8 +545,7 @@ public void IsValidValidatesSpecifiedFields() var oddValidator = new Mock(); oddValidator.Setup(c => c.Validate(It.IsAny())).Returns(v => { - Assert.IsAssignableFrom(v.ObjectInstance); - var context = (HttpContextBase)v.ObjectInstance; + var context = Assert.IsAssignableFrom(v.ObjectInstance); int value; if (!Int32.TryParse(context.Request.Form["foo"], out value)) { diff --git a/test/System.Web.WebPages.Test/Validation/ValidatorTest.cs b/test/System.Web.WebPages.Test/Validation/ValidatorTest.cs index fbc9a1461..e7bf20ec5 100644 --- a/test/System.Web.WebPages.Test/Validation/ValidatorTest.cs +++ b/test/System.Web.WebPages.Test/Validation/ValidatorTest.cs @@ -339,10 +339,10 @@ public void GetClientValidationRulesForStringLengthValidatorWithDefaultErrorMess var result = validator.ClientValidationRule; // Assert - Assert.Equal(result.ValidationType, "length"); - Assert.Equal(result.ErrorMessage, "String must be between 4 and 6 characters."); - Assert.Equal(result.ValidationParameters["min"], 4); - Assert.Equal(result.ValidationParameters["max"], 6); + Assert.Equal("length", result.ValidationType); + Assert.Equal("String must be between 4 and 6 characters.", result.ErrorMessage); + Assert.Equal(4, result.ValidationParameters["min"]); + Assert.Equal(6, result.ValidationParameters["max"]); } [Fact] @@ -356,9 +356,9 @@ public void GetClientValidationRulesForStringLengthValidatorWithCustomErrorMessa var result = validator.ClientValidationRule; // Assert - Assert.Equal(result.ValidationType, "length"); - Assert.Equal(result.ErrorMessage, "Must be at least 6 letters."); - Assert.Equal(result.ValidationParameters["max"], 6); + Assert.Equal("length", result.ValidationType); + Assert.Equal("Must be at least 6 letters.", result.ErrorMessage); + Assert.Equal(6, result.ValidationParameters["max"]); } [Fact] diff --git a/test/System.Web.WebPages.Test/WebPage/DisplayInfoTest.cs b/test/System.Web.WebPages.Test/WebPage/DisplayInfoTest.cs index 38d29bd11..98691ae93 100644 --- a/test/System.Web.WebPages.Test/WebPage/DisplayInfoTest.cs +++ b/test/System.Web.WebPages.Test/WebPage/DisplayInfoTest.cs @@ -16,6 +16,7 @@ public void GuardClauses() Assert.ThrowsArgumentNull(() => new DisplayInfo("testPath", displayMode: null), "displayMode"); } + [Fact] public void ConstructorSetsDisplayInfoProperties() { // Arrange @@ -30,6 +31,7 @@ public void ConstructorSetsDisplayInfoProperties() Assert.Equal(displayMode, info.DisplayMode); } + [Fact] public void ConstructorSetsEmptyFilePath() { // Act & Assert diff --git a/test/System.Web.WebPages.Test/WebPage/DisplayModeProviderTest.cs b/test/System.Web.WebPages.Test/WebPage/DisplayModeProviderTest.cs index b8228a969..891dc4e74 100644 --- a/test/System.Web.WebPages.Test/WebPage/DisplayModeProviderTest.cs +++ b/test/System.Web.WebPages.Test/WebPage/DisplayModeProviderTest.cs @@ -169,8 +169,8 @@ public void GetAvailableDisplayModesForContextWithRestrictingPageElements() var availableDisplayModes = displayModeProvider.GetAvailableDisplayModesForContext(httpContext.Object, displayMode2.Object, requireConsistentDisplayMode: true).ToList(); // Assert - Assert.Equal(1, availableDisplayModes.Count); - Assert.Equal(displayMode3.Object, availableDisplayModes[0]); + var availableDisplayMode = Assert.Single(availableDisplayModes); + Assert.Equal(displayMode3.Object, availableDisplayMode); } [Fact] @@ -225,8 +225,8 @@ public void GetAvailableDisplayModesReturnsOnlyModesThatCanHandleContext() var availableDisplayModes = displayModeProvider.GetAvailableDisplayModesForContext(httpContext.Object, displayMode1.Object, requireConsistentDisplayMode: false).ToList(); // Assert - Assert.Equal(1, availableDisplayModes.Count); - Assert.Equal(displayMode2.Object, availableDisplayModes[0]); + IDisplayMode availableDisplayMode = Assert.Single(availableDisplayModes); + Assert.Equal(displayMode2.Object, availableDisplayMode); } } } diff --git a/test/System.Web.WebPages.Test/WebPage/DynamicPageDataDictionaryTest.cs b/test/System.Web.WebPages.Test/WebPage/DynamicPageDataDictionaryTest.cs index 3ef2a90ef..a31a78dd3 100644 --- a/test/System.Web.WebPages.Test/WebPage/DynamicPageDataDictionaryTest.cs +++ b/test/System.Web.WebPages.Test/WebPage/DynamicPageDataDictionaryTest.cs @@ -162,7 +162,7 @@ public void CountTest() dynamic dyn = d; Assert.IsType(dyn.Count); d.Add("x", 1); - Assert.Equal(1, d.Count); + Assert.Single(d); d.Add("y", 2); Assert.Equal(2, d.Count); dyn.Count = "foo"; diff --git a/test/System.Web.WebPages.Test/WebPage/LayoutTest.cs b/test/System.Web.WebPages.Test/WebPage/LayoutTest.cs index a7aa150db..0f56ea00a 100644 --- a/test/System.Web.WebPages.Test/WebPage/LayoutTest.cs +++ b/test/System.Web.WebPages.Test/WebPage/LayoutTest.cs @@ -65,8 +65,8 @@ public void SourceFileWithLayoutPageTest() var result = Utils.RenderWebPage(page, request: request.Object); Assert.Equal(2, page.PageContext.SourceFiles.Count); - Assert.True(page.PageContext.SourceFiles.Contains("~/MyApp/index.cshtml")); - Assert.True(page.PageContext.SourceFiles.Contains("~/MyFiles/Layout.cshtml")); + Assert.Contains("~/MyApp/index.cshtml", page.PageContext.SourceFiles); + Assert.Contains("~/MyFiles/Layout.cshtml", page.PageContext.SourceFiles); } private static void LayoutBasicTestInternal(string layoutPath, string pagePath = "~/index.cshtml", string layoutPage = "Layout.cshtml") @@ -75,7 +75,7 @@ private static void LayoutBasicTestInternal(string layoutPath, string pagePath = // PageData["Title"] = "MyPage"; // Layout = "Layout.cshtml"; // WriteLiteral("hello world"); - // + // // The layout page ~/Layout.cshtml does the following: // WriteLiteral(Title); // RenderBody(); @@ -109,7 +109,7 @@ public void LayoutNestedTest() // PageData["Title"] = "MyPage"; // Layout = "Layout1.cshtml"; // WriteLiteral("hello world"); - // + // // The first layout page ~/Layout1.cshtml does the following: // Layout = "Layout2.cshtml"; // WriteLiteral(""); @@ -291,7 +291,7 @@ public void LayoutSectionsNestedNamesTest() // The page ~/layout1.cshtml does the following: // Layout = "Layout2.cshtml"; // @section body { - // body in layout1 + // body in layout1 // @RenderSection("body") // } // diff --git a/test/System.Web.WebPages.Test/WebPage/PageDataDictionaryTest.cs b/test/System.Web.WebPages.Test/WebPage/PageDataDictionaryTest.cs index 438df2c03..8ed9b74be 100644 --- a/test/System.Web.WebPages.Test/WebPage/PageDataDictionaryTest.cs +++ b/test/System.Web.WebPages.Test/WebPage/PageDataDictionaryTest.cs @@ -54,9 +54,9 @@ public void ContainsTest() var d = new PageDataDictionary(); var item = new KeyValuePair("x", 1); d.Add(item); - Assert.True(d.Contains(item)); + Assert.Contains>(item, d); var item2 = new KeyValuePair("y", 2); - Assert.False(d.Contains(item2)); + Assert.DoesNotContain>(item2, d); } [Fact] @@ -106,9 +106,9 @@ public void RemoveTest1() var d = new PageDataDictionary(); var item = new KeyValuePair("x", 2); d.Add(item); - Assert.True(d.Contains(item)); + Assert.Contains>(item, d); d.Remove(item); - Assert.False(d.Contains(item)); + Assert.DoesNotContain>(item, d); } [Fact] @@ -137,7 +137,7 @@ public void CountTest() { var d = new PageDataDictionary(); d.Add("x", 1); - Assert.Equal(1, d.Count); + Assert.Single(d); d.Add("y", 2); Assert.Equal(2, d.Count); } diff --git a/test/System.Web.WebPages.Test/WebPage/UrlDataTest.cs b/test/System.Web.WebPages.Test/WebPage/UrlDataTest.cs index 47b9373cb..71f6e50fb 100644 --- a/test/System.Web.WebPages.Test/WebPage/UrlDataTest.cs +++ b/test/System.Web.WebPages.Test/WebPage/UrlDataTest.cs @@ -36,8 +36,8 @@ public void IndexOfTest() var item = "!!@#$#$"; var item2 = "13l53125"; var d = new UrlDataList(item + "/" + item2); - Assert.True(d.IndexOf(item) == 0); - Assert.True(d.IndexOf(item2) == 1); + Assert.Equal(0, d.IndexOf(item)); + Assert.Equal(1, d.IndexOf(item2)); } [Fact] @@ -52,7 +52,7 @@ public void ContainsTest() { var item = "!!@#$#$"; var d = new UrlDataList(item); - Assert.True(d.Contains(item)); + Assert.Contains(item, d); } [Fact] @@ -92,14 +92,14 @@ public void RemoveAtTest() public void CountTest() { var d = new UrlDataList("x"); - Assert.Equal(1, d.Count); + Assert.Single(d); } [Fact] public void IsReadOnlyTest() { var d = new UrlDataList(null); - Assert.Equal(true, d.IsReadOnly); + Assert.True(d.IsReadOnly); } [Fact] diff --git a/test/System.Web.WebPages.Test/WebPage/WebPageHttpHandlerTest.cs b/test/System.Web.WebPages.Test/WebPage/WebPageHttpHandlerTest.cs index 027cc7019..f0b44985c 100644 --- a/test/System.Web.WebPages.Test/WebPage/WebPageHttpHandlerTest.cs +++ b/test/System.Web.WebPages.Test/WebPage/WebPageHttpHandlerTest.cs @@ -52,14 +52,14 @@ public void SourceFileHeaderTest() Mock context = Utils.CreateTestContext(httpRequest.Object, httpResponse.Object); var page = Utils.CreatePage(p => p.Write(contents)); - // Act + // Act var webPageHttpHandler = new WebPageHttpHandler(page); webPageHttpHandler.ProcessRequestInternal(context.Object); // Assert Assert.Equal(contents, writer.ToString()); - Assert.Equal(1, page.PageContext.SourceFiles.Count); - Assert.True(page.PageContext.SourceFiles.Contains("~/index.cshtml")); + Assert.Single(page.PageContext.SourceFiles); + Assert.Contains("~/index.cshtml", page.PageContext.SourceFiles); } [Fact] @@ -87,8 +87,8 @@ public void GenerateSourceFilesHeaderGenerates2047EncodedValue() WebPageHttpHandler.GenerateSourceFilesHeader(webPageContext); // Assert - Assert.Equal(headerKey, "X-SourceFiles"); - Assert.Equal(headerValue, "=?UTF-8?B?Zm9vfGJhcnzOuw==?="); + Assert.Equal("X-SourceFiles", headerKey); + Assert.Equal("=?UTF-8?B?Zm9vfGJhcnzOuw==?=", headerValue); } [Fact] @@ -166,8 +166,7 @@ public void CreateFromVirtualPathTest() // Act IHttpHandler handler = WebPageHttpHandler.CreateFromVirtualPath(virtualPath, new VirtualPathFactoryManager(mockBuildManager.Object)); - Assert.IsType(handler); - WebPageHttpHandler webPageHttpHandler = (WebPageHttpHandler)handler; + WebPageHttpHandler webPageHttpHandler = Assert.IsType(handler); webPageHttpHandler.ProcessRequestInternal(httpContext.Object); // Assert diff --git a/test/System.Web.WebPages.Test/WebPage/WebPageTest.cs b/test/System.Web.WebPages.Test/WebPage/WebPageTest.cs index 224e73ff3..74bf0dcd7 100644 --- a/test/System.Web.WebPages.Test/WebPage/WebPageTest.cs +++ b/test/System.Web.WebPages.Test/WebPage/WebPageTest.cs @@ -172,14 +172,18 @@ public void AnonymousObjectModelTest() public void SessionPropertyTest() { var page = CreateMockPageWithPostContext().Object; +#pragma warning disable xUnit2013 // Do not use equality check to check for collection size. Assert.Equal(0, page.Session.Count); +#pragma warning restore xUnit2013 // Do not use equality check to check for collection size. } [Fact] public void AppStatePropertyTest() { var page = CreateMockPageWithPostContext().Object; +#pragma warning disable xUnit2013 // Do not use equality check to check for collection size. Assert.Equal(0, page.AppState.Count); +#pragma warning restore xUnit2013 // Do not use equality check to check for collection size. } [Fact] diff --git a/test/System.Web.WebPages.Test/packages.config b/test/System.Web.WebPages.Test/packages.config index 2388b969c..cafc6212c 100644 --- a/test/System.Web.WebPages.Test/packages.config +++ b/test/System.Web.WebPages.Test/packages.config @@ -1,12 +1,13 @@  - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/test/WebApiHelpPage.Test/WebApiHelpPage.Test.csproj b/test/WebApiHelpPage.Test/WebApiHelpPage.Test.csproj index 31f1692ee..436b124a7 100644 --- a/test/WebApiHelpPage.Test/WebApiHelpPage.Test.csproj +++ b/test/WebApiHelpPage.Test/WebApiHelpPage.Test.csproj @@ -1,6 +1,7 @@  - + + {291EF478-BF24-4935-BC78-E0DCCD0C9A1B} @@ -14,17 +15,17 @@ - - ..\..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll + + ..\..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll True - - ..\..\packages\Moq.4.5.21\lib\net45\Moq.dll + + ..\..\packages\Moq.4.18.4\lib\net462\Moq.dll True - - False - ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + True @@ -40,19 +41,19 @@ - ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll True - - ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll True - - ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll True - - ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll True @@ -134,14 +135,20 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + + + - $(WebStackToolsPath)WebStack.targets - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - + Debug @@ -33,11 +36,8 @@ false false - - v4.5 - - - 5 + + 9.0 true diff --git a/tools/WebStack.tasks.targets b/tools/WebStack.tasks.targets index f3a36dbbc..efbf42d40 100644 --- a/tools/WebStack.tasks.targets +++ b/tools/WebStack.tasks.targets @@ -1,7 +1,16 @@ + + Microsoft.Build.Tasks.Core + Microsoft.Build.Tasks.v$(MSBuildToolsVersion) + Microsoft.Build.Tasks.v4.0 + + Microsoft.Build.Tasks.Core + $(MSBuildToolsPath)\$(BuildTaskAssemblyReference).dll + + - + @@ -17,36 +26,42 @@ 0) + { + toParse = toParse.Substring(0, index); + } } else { toParse = null; } - + Version current; Version parsed; - + if (toParse != null && Version.TryParse(toParse, out parsed)) { current = parsed; @@ -56,16 +71,16 @@ // Treat a missing or invalid version like V0.0 (which will trigger a delete and download). current = new Version(0, 0); } - + if (current < minimumRequiredVersion) { File.Delete(OutputFileName); } } - + if (!File.Exists(OutputFileName)) { - Log.LogMessage("Downloading latest version of NuGet.exe..."); + Log.LogMessage(MessageImportance.High, "Downloading latest version of NuGet.exe..."); WebClient webClient = new WebClient(); webClient.DownloadFile("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", OutputFileName); } @@ -82,59 +97,7 @@ - - - - - - - - - - - - - - - - - - - - - + @@ -145,13 +108,18 @@ + + + + [0-9A-Fa-f]+);", + RegexOptions.Multiline | RegexOptions.Compiled); int testsPassed = 0; int testsFailed = 0; int testsSkipped = 0; @@ -160,8 +128,20 @@ foreach (string testResultFile in testResultFiles) { + // Replace potentially illegal escaped characters (if they get through validations done during Save). + string fullPath = Path.GetFullPath(testResultFile); + string originalText = File.ReadAllText(fullPath); + bool matched = regex.IsMatch(originalText); + + if (matched) + { + File.SetAttributes(fullPath, File.GetAttributes(fullPath) & ~FileAttributes.ReadOnly); + File.WriteAllText(fullPath, regex.Replace(originalText, "\0x${char}"), Encoding.UTF8); + } + + // Collect test failure information from results file. XElement xml; - using (FileStream fileStream = File.OpenRead(testResultFile)) + using (FileStream fileStream = File.OpenRead(fullPath)) { xml = XElement.Load(fileStream); } @@ -169,16 +149,29 @@ var assemblies = xml.Elements(XName.Get("assembly")); foreach (XElement assembly in assemblies) { - int failures = Int32.Parse(assembly.Attribute(XName.Get("failed")).Value); + XAttribute failed = assembly.Attribute(XName.Get("failed")); + if (failed == null) + { + // Occasionally xUnit does not write information about test assembly completion. + XAttribute name = assembly.Attribute(XName.Get("name")); + Log.LogWarning( + "No results in {0} for {1}.", + testResultFile, + name == null ? "unknown assembly" : name.Value); - testsPassed += Int32.Parse(assembly.Attribute(XName.Get("passed")).Value); + continue; + } + + int failures = Int32.Parse(failed.Value); testsFailed += failures; + + testsPassed += Int32.Parse(assembly.Attribute(XName.Get("passed")).Value); testsSkipped += Int32.Parse(assembly.Attribute(XName.Get("skipped")).Value); timeSpent += Decimal.Parse(assembly.Attribute(XName.Get("time")).Value); if (failures > 0) { - foreach (XElement classWithFailure in assembly.Elements(XName.Get("class")) + foreach (XElement classWithFailure in assembly.Elements(XName.Get("collection")) .Where(c => Int32.Parse(c.Attribute(XName.Get("failed")).Value) > 0)) { foreach (XElement failure in classWithFailure.Elements(XName.Get("test")) @@ -191,23 +184,32 @@ } } + // Log all test failures. if (testFailures.Count > 0) { - Console.WriteLine(); - Console.WriteLine(" Test Failures:"); - ConsoleColor originalColor = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Red; + Log.LogMessage(MessageImportance.High, string.Empty); + Log.LogError("Tests failed..."); foreach (string testFailure in testFailures) { - Console.WriteLine(" " + testFailure); + // Provide the list of failed tests but don't repeat it in the build summary. List + // is usually less helpful than errors from tests themselves (which are repeated) + // because those errors include the exact failure locations. On the other hand, + // this is more compact. + Log.LogMessage(MessageImportance.High, testFailure); } - Console.ForegroundColor = originalColor; } - Console.WriteLine(); - Console.WriteLine(" Tests passed: {0}, Tests failed: {1}, Tests skipped: {2}", testsPassed, testsFailed, testsSkipped); - Console.WriteLine(" Time spent running tests: {0} seconds", timeSpent); - return true; + // Log summary of all results. + Log.LogMessage(MessageImportance.High, string.Empty); + Log.LogMessage(MessageImportance.High, + "Tests passed: {0}, Tests failed: {1}, Tests skipped: {2}", + testsPassed, + testsFailed, + testsSkipped); + Log.LogMessage(MessageImportance.High, + "Time spent running tests: {0} seconds", timeSpent); + + return !Log.HasLoggedErrors; } catch (Exception ex) { @@ -218,4 +220,4 @@ - \ No newline at end of file + diff --git a/tools/WebStack.testing.targets b/tools/WebStack.testing.targets new file mode 100644 index 000000000..9a134d52b --- /dev/null +++ b/tools/WebStack.testing.targets @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + <_ExitCodes Include="$(TestAssembly)" Code="$(_ExitCode)" /> + + + diff --git a/tools/WebStack.xunit.targets b/tools/WebStack.xunit.targets deleted file mode 100644 index 14d923ac6..000000000 --- a/tools/WebStack.xunit.targets +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/src/Microsoft.Web.FxCop/Microsoft.Web.FxCop.csproj b/tools/src/Microsoft.Web.FxCop/Microsoft.Web.FxCop.csproj index 13afb5d79..2fc7c9bb4 100644 --- a/tools/src/Microsoft.Web.FxCop/Microsoft.Web.FxCop.csproj +++ b/tools/src/Microsoft.Web.FxCop/Microsoft.Web.FxCop.csproj @@ -10,7 +10,8 @@ Properties Microsoft.Web.FxCop Microsoft.Web.FxCop - v4.0 + + v4.7.2 bin\$(Configuration) @@ -31,7 +32,7 @@ 4 - $(MSBuildProgramFiles32)\Microsoft Visual Studio $(VisualStudioVersion)\Team Tools\Static Analysis Tools\FxCop\ + $(VsInstallRoot)\Team Tools\Static Analysis Tools\FxCop\ diff --git a/tools/vslicense/dotnet-library-license.htm b/tools/vslicense/dotnet-library-license.htm new file mode 100644 index 000000000..902081889 --- /dev/null +++ b/tools/vslicense/dotnet-library-license.htm @@ -0,0 +1,476 @@ + + + + + + + +
+

MICROSOFT SOFTWARE LICENSE TERMS

+
+

MICROSOFT .NET LIBRARY

+
+

These license terms are an agreement between you and Microsoft Corporation (or based on where you live, one of its affiliates). They apply to the software named above. The terms also apply + to any Microsoft services or updates for the software, except to the extent those have different terms.

+
+

If you comply with these license terms, you have the rights below.

+
+

+1.    +INSTALLATION AND USE RIGHTS.

+

+You may install and use any number of copies of the software +to develop and test your applications.  +

+

2.    +THIRD PARTY COMPONENTS. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices + file(s) accompanying the software.

+

3.    +ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS.

+

a.     +DISTRIBUTABLE CODE.  +The software is comprised of Distributable Code. �Distributable Code� is code that you are permitted to distribute in applications + you develop if you comply with the terms below.

+

+i.      +Right to Use and Distribute. +

+

+        +You may copy and distribute the object code form of the software.

+

+        +Third Party Distribution. You may permit distributors of your applications to copy and distribute the Distributable Code as part of those applications.

+

+ii.     +Distribution Requirements. For any Distributable Code you distribute, you must

+

+        +use the Distributable Code in your applications and not as a standalone distribution;

+

+        +require distributors and external end users to agree to terms that protect it at least as much as this agreement; and

+

+        +indemnify, defend, and hold harmless Microsoft from any claims, including attorneys� fees, related to the distribution or use of your applications, except to the extent + that any claim is based solely on the unmodified Distributable Code.

+

+iii.   +Distribution Restrictions. You may not

+

+        +use Microsoft�s trademarks in your applications� names or in a way that suggests your applications come from or are endorsed by Microsoft; or

+

+        +modify or distribute the source code of any Distributable Code so that any part of it becomes subject to an Excluded License. An �Excluded License� is one that requires, + as a condition of use, modification or distribution of code, that (i) it be disclosed or distributed in source code form; or (ii) others have the right to modify it.

+

4.    +DATA.

+

a.     +Data Collection. The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information + to provide services and improve our products and services.  You may opt-out of many of these scenarios, but not all, as described in the software documentation.  There are also some features in the software that may enable you and + Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with Microsoft�s privacy statement. Our privacy + statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can + learn more about data collection and its use from the software documentation and our privacy statement. Your use of the software operates as your consent to these practices.

+

b.    +Processing of Personal Data. +To the extent Microsoft is a processor or subprocessor of personal data in connection with the software, Microsoft makes the commitments in the European Union General Data Protection Regulation Terms of the + Online Services Terms to all customers effective May 25, 2018, at https://docs.microsoft.com/en-us/legal/gdpr.

+

5.    +Scope of License. The software is licensed, not sold. This agreement only gives you some rights + to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations + in the software that only allow you to use it in certain ways. You may not

+

        +work around any technical limitations in the software;

+

        +reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the software, except and to the extent required by third party licensing terms governing use of certain + open source components that may be included in the software;

+

        +remove, minimize, block or modify any notices of Microsoft or its suppliers in the software; +

+

        +use the software in any way that is against the law; or

+

        +share, publish, rent or lease the software, provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party.

+

6.    +Export Restrictions. +You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information + on export restrictions, visit www.microsoft.com/exporting. + 

+

7.    +SUPPORT SERVICES. +Because this software is �as is,� we may not provide support services for it.

+

8.    +Entire Agreement. This agreement, and the terms for supplements, updates, Internet-based services and support services that you + use, are the entire agreement for the software and support services.

+

9.    +Applicable Law.  +If you acquired the software in the United States, Washington law applies to interpretation of and claims for breach of this agreement, and the laws of the state where you live apply to all other claims. + If you acquired the software in any other country, its laws apply.

+

10. +CONSUMER RIGHTS; REGIONAL VARIATIONS. +This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, + you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the + below regions, or mandatory country law applies, then the following provisions apply to you:

+

a)    +Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights.

+

b)    +Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from + the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device + or software.

+

c)    +Germany and Austria.

+

(i)        +Warranty. The software will perform substantially as described in any Microsoft materials that accompany it. However, Microsoft gives no contractual guarantee in relation to the software.

+

(ii)       +Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as in case of death or personal or physical injury, Microsoft is liable according to the statutory law.

+

Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, + the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of + slight negligence, Microsoft will not be liable for slight negligence

+

11. +Disclaimer of Warranty. THE SOFTWARE IS LICENSED �AS-IS.� YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. + TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +

+

12. +Limitation on and Exclusion of Remedies and Damages. +YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.

+

This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, breach of + warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.

+

It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country + may not allow the exclusion or limitation of incidental, consequential or other damages.

+

 

+
+ + diff --git a/tools/vslicense/dotnet-library-license.md b/tools/vslicense/dotnet-library-license.md new file mode 100644 index 000000000..18a6fd30c --- /dev/null +++ b/tools/vslicense/dotnet-library-license.md @@ -0,0 +1,87 @@ +**MICROSOFT SOFTWARE LICENSE TERMS** + +**MICROSOFT .NET LIBRARY** + +------------------------------------------------------------------------------ +These license terms are an agreement between you and Microsoft Corporation (or based on where you live, one of its affiliates). They apply to the software named above. The terms also apply to any Microsoft services or updates for the software, except to the extent those have different terms. + +------------------------------------------------------------------------------ +**IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.** + +**1. INSTALLATION AND USE RIGHTS.** + +> You may install and use any number of copies of the software to develop and test your applications. + +**2. THIRD PARTY COMPONENTS.** The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. + +**3. ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS.** + +> **a. DISTRIBUTABLE CODE.** The software is comprised of Distributable Code. "Distributable Code" is code that you are permitted to distribute in applications you develop if you comply with the terms below. + +>> **i. Right to Use and Distribute.** + +>> - You may copy and distribute the object code form of the software. + +>> - Third Party Distribution. You may permit distributors of your applications to copy and distribute the Distributable Code as part of those applications. + +>> **ii. Distribution Requirements. For any Distributable Code you distribute, you must** + +>> - use the Distributable Code in your applications and not as a standalone distribution; + +>> - require distributors and external end users to agree to terms that protect it at least as much as this agreement; and + +>> - indemnify, defend, and hold harmless Microsoft from any claims, including attorneys' fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified Distributable Code. + +>> **iii. Distribution Restrictions. You may not** + +>> - use Microsoft's trademarks in your applications' names or in a way that suggests your applications come from or are endorsed by Microsoft; or + +>> - modify or distribute the source code of any Distributable Code so that any part of it becomes subject to an Excluded License. An "Excluded License" is one that requires, as a condition of use, modification or distribution of code, that (i) it be disclosed or distributed in source code form; or (ii) others have the right to modify it. + +**4. DATA.** + +> **a. Data Collection.** The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the software documentation. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and its use from the software documentation and our privacy statement. Your use of the software operates as your consent to these practices. + +> **b. Processing of Personal Data.** To the extent Microsoft is a processor or subprocessor of personal data in connection with the software, Microsoft makes the commitments in the European Union General Data Protection Regulation Terms of the Online Services Terms to all customers effective May 25, 2018, at https://docs.microsoft.com/en-us/legal/gdpr. + +**5. SCOPE OF LICENSE.** The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not + +> - work around any technical limitations in the software; + +> - reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the software, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the software; + +> - remove, minimize, block or modify any notices of Microsoft or its suppliers in the software; + +> - use the software in any way that is against the law; or + +> - share, publish, rent or lease the software, provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. + +**6. EXPORT RESTRICTIONS.** You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting. + +**7. SUPPORT SERVICES.** Because this software is "as is", we may not provide support services for it. + +**8. ENTIRE AGREEMENT.** This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services. + +**9. APPLICABLE LAW.** If you acquired the software in the United States, Washington law applies to interpretation of and claims for breach of this agreement, and the laws of the state where you live apply to all other claims. If you acquired the software in any other country, its laws apply. + +**10. CONSUMER RIGHTS; REGIONAL VARIATIONS.** This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: + +> **a) Australia.** You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights. + +> **b) Canada.** If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software. + +> **c) Germany and Austria.** + +>> **(i) Warranty.** The software will perform substantially as described in any Microsoft materials that accompany it. However, Microsoft gives no contractual guarantee in relation to the software. + +>> **(ii) Limitation of Liability.** In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as in case of death or personal or physical injury, Microsoft is liable according to the statutory law. + +> Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence + +**11. Disclaimer of Warranty. THE SOFTWARE IS LICENSED "AS-IS". YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.** + +**12. Limitation on and Exclusion of Remedies and Damages. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.** + +This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. + +It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages. \ No newline at end of file