diff --git a/src/Mvc/.editorconfig b/src/Mvc/.editorconfig new file mode 100644 index 0000000000..abd3d48553 --- /dev/null +++ b/src/Mvc/.editorconfig @@ -0,0 +1,56 @@ +# EditorConfig is awesome:http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Don't use tabs for indentation. +[*] +indent_style = space +# (Please don't specify an indent_size here; that has too many unintended consequences.) + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 + +# Xml project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# Xml config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 + +# Dotnet code style settings: +[*.cs] +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true + +# Don't use this. qualifier +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion + +# use int x = .. over Int32 +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion + +# use int.MaxValue over Int32.MaxValue +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Require var all the time. +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Disallow throw expressions. +csharp_style_throw_expression = false:suggestion + +# Newline settings +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true diff --git a/src/Mvc/.gitignore b/src/Mvc/.gitignore new file mode 100644 index 0000000000..e38f0aa101 --- /dev/null +++ b/src/Mvc/.gitignore @@ -0,0 +1,43 @@ +[Oo]bj/ +[Bb]in/ +TestResults/ +.nuget/ +.build/ +.testPublish/ +*.sln.ide/ +_ReSharper.*/ +packages/ +artifacts/ +PublishProfiles/ +.vs/ +bower_components/ +node_modules/ +debugSettings.json +project.lock.json +*.user +*.suo +*.cache +*.docstates +_ReSharper.* +nuget.exe +*net45.csproj +*net451.csproj +*k10.csproj +*.psess +*.vsp +*.pidb +*.userprefs +*DS_Store +*.ncrunchsolution +*.*sdf +*.ipch +.settings +*.sln.ide +node_modules +*launchSettings.json +*.orig +.vscode/ +global.json +BenchmarkDotNet.Artifacts/ +.idea/ +msbuild.binlog diff --git a/src/Mvc/Directory.Build.props b/src/Mvc/Directory.Build.props new file mode 100644 index 0000000000..fad2bb0610 --- /dev/null +++ b/src/Mvc/Directory.Build.props @@ -0,0 +1,21 @@ + + + + + + + + + Microsoft ASP.NET Core MVC + https://github.com/aspnet/Mvc + git + $(MSBuildThisFileDirectory) + $(MSBuildThisFileDirectory)build\Key.snk + true + true + true + + + diff --git a/src/Mvc/Directory.Build.targets b/src/Mvc/Directory.Build.targets new file mode 100644 index 0000000000..eb03b2565f --- /dev/null +++ b/src/Mvc/Directory.Build.targets @@ -0,0 +1,6 @@ + + + $(MicrosoftNETCoreApp21PackageVersion) + $(NETStandardLibrary20PackageVersion) + + diff --git a/src/Mvc/Mvc.NoFun.sln b/src/Mvc/Mvc.NoFun.sln new file mode 100644 index 0000000000..33f4a84d2f --- /dev/null +++ b/src/Mvc/Mvc.NoFun.sln @@ -0,0 +1,595 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2036 +MinimumVisualStudioVersion = 15.0.26730.03 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{32285FA4-6B46-4D6B-A840-2B13E4C8B58E}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}" + ProjectSection(SolutionItems) = preProject + test\Directory.Build.props = test\Directory.Build.props + test\MvcTests.ruleset = test\MvcTests.ruleset + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc", "src\Microsoft.AspNetCore.Mvc\Microsoft.AspNetCore.Mvc.csproj", "{079EFA1F-0B0A-4853-B27B-5780D111CD85}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor", "src\Microsoft.AspNetCore.Mvc.Razor\Microsoft.AspNetCore.Mvc.Razor.csproj", "{314E9AD6-2FFC-4A92-A8AD-510658C64F1E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Core", "src\Microsoft.AspNetCore.Mvc.Core\Microsoft.AspNetCore.Mvc.Core.csproj", "{C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Test", "test\Microsoft.AspNetCore.Mvc.Razor.Test\Microsoft.AspNetCore.Mvc.Razor.Test.csproj", "{3F6E355E-4869-41D9-943B-D54771221A7F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Core.Test", "test\Microsoft.AspNetCore.Mvc.Core.Test\Microsoft.AspNetCore.Mvc.Core.Test.csproj", "{A8AA326E-8EE8-4F11-B750-23028E0949D7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Test", "test\Microsoft.AspNetCore.Mvc.Test\Microsoft.AspNetCore.Mvc.Test.csproj", "{5F945B82-FE5F-425C-956C-8BC2F2020254}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.WebApiCompatShim", "src\Microsoft.AspNetCore.Mvc.WebApiCompatShim\Microsoft.AspNetCore.Mvc.WebApiCompatShim.csproj", "{23D30B8C-04B1-4577-A604-ED27EA1E4A0E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.WebApiCompatShimTest", "test\Microsoft.AspNetCore.Mvc.WebApiCompatShimTest\Microsoft.AspNetCore.Mvc.WebApiCompatShimTest.csproj", "{5DE8E4D9-AACD-4B5F-819F-F091383FB996}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TagHelpers", "src\Microsoft.AspNetCore.Mvc.TagHelpers\Microsoft.AspNetCore.Mvc.TagHelpers.csproj", "{B2347320-308E-4D2B-AEC8-005DFA68B0C9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TagHelpers.Test", "test\Microsoft.AspNetCore.Mvc.TagHelpers.Test\Microsoft.AspNetCore.Mvc.TagHelpers.Test.csproj", "{860119ED-3DB1-424D-8D0A-30132A8A7D96}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TestCommon", "test\Microsoft.AspNetCore.Mvc.TestCommon\Microsoft.AspNetCore.Mvc.TestCommon.csproj", "{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.IntegrationTests", "test\Microsoft.AspNetCore.Mvc.IntegrationTests\Microsoft.AspNetCore.Mvc.IntegrationTests.csproj", "{864FA09D-1E48-403A-A6C8-4F079D2A30F0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Abstractions", "src\Microsoft.AspNetCore.Mvc.Abstractions\Microsoft.AspNetCore.Mvc.Abstractions.csproj", "{1154203C-7579-4525-906E-BC55268421C1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ApiExplorer", "src\Microsoft.AspNetCore.Mvc.ApiExplorer\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj", "{A2B72833-5D70-4C42-AE85-E0319926FB8A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ApiExplorer.Test", "test\Microsoft.AspNetCore.Mvc.ApiExplorer.Test\Microsoft.AspNetCore.Mvc.ApiExplorer.Test.csproj", "{4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Abstractions.Test", "test\Microsoft.AspNetCore.Mvc.Abstractions.Test\Microsoft.AspNetCore.Mvc.Abstractions.Test.csproj", "{DA000953-7532-4DF5-8DB9-8143DF98D999}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ViewFeatures", "src\Microsoft.AspNetCore.Mvc.ViewFeatures\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj", "{3F8B8FC1-9FE4-4788-8991-367113E8D7AD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Formatters.Json", "src\Microsoft.AspNetCore.Mvc.Formatters.Json\Microsoft.AspNetCore.Mvc.Formatters.Json.csproj", "{3FC8D9D6-9352-43A3-8E81-422F270085B7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Formatters.Xml", "src\Microsoft.AspNetCore.Mvc.Formatters.Xml\Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj", "{42C81540-CD47-4C68-A7A3-2A93B9C3B210}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Formatters.Json.Test", "test\Microsoft.AspNetCore.Mvc.Formatters.Json.Test\Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj", "{493780DA-E696-40FF-BD12-4A5C5736F292}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Formatters.Xml.Test", "test\Microsoft.AspNetCore.Mvc.Formatters.Xml.Test\Microsoft.AspNetCore.Mvc.Formatters.Xml.Test.csproj", "{22019146-BDFA-442E-8C8E-345FB9644578}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Cors", "src\Microsoft.AspNetCore.Mvc.Cors\Microsoft.AspNetCore.Mvc.Cors.csproj", "{9A07EEA2-942E-4969-9D41-799B6E2D1FF5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.DataAnnotations", "src\Microsoft.AspNetCore.Mvc.DataAnnotations\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj", "{2DD786CA-7AF7-437A-B499-801A589B9A1C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Cors.Test", "test\Microsoft.AspNetCore.Mvc.Cors.Test\Microsoft.AspNetCore.Mvc.Cors.Test.csproj", "{6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.DataAnnotations.Test", "test\Microsoft.AspNetCore.Mvc.DataAnnotations.Test\Microsoft.AspNetCore.Mvc.DataAnnotations.Test.csproj", "{827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ViewFeatures.Test", "test\Microsoft.AspNetCore.Mvc.ViewFeatures.Test\Microsoft.AspNetCore.Mvc.ViewFeatures.Test.csproj", "{60873DFA-97B9-419E-BAA3-940FC9B07085}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Localization", "src\Microsoft.AspNetCore.Mvc.Localization\Microsoft.AspNetCore.Mvc.Localization.csproj", "{50893B10-5735-4F35-9995-F81DA3F0189E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Localization.Test", "test\Microsoft.AspNetCore.Mvc.Localization.Test\Microsoft.AspNetCore.Mvc.Localization.Test.csproj", "{8FC726B5-E766-44E0-8B38-1313B6D8D9A7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TestDiagnosticListener", "test\Microsoft.AspNetCore.Mvc.TestDiagnosticListener\Microsoft.AspNetCore.Mvc.TestDiagnosticListener.csproj", "{9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MvcSandbox", "samples\MvcSandbox\MvcSandbox.csproj", "{14ED4476-9F24-4776-8417-EA6927F6C9C9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.RazorPages", "src\Microsoft.AspNetCore.Mvc.RazorPages\Microsoft.AspNetCore.Mvc.RazorPages.csproj", "{CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.RazorPages.Test", "test\Microsoft.AspNetCore.Mvc.RazorPages.Test\Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj", "{0AB46520-F441-4E01-B444-08F4D23F8B1B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Performance", "benchmarks\Microsoft.AspNetCore.Mvc.Performance\Microsoft.AspNetCore.Mvc.Performance.csproj", "{28D4DA20-6E13-47F9-80AE-D6AA7699CC35}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4E1795C3-60C5-4AD2-A15F-93F6CE8FAD36}" + ProjectSection(SolutionItems) = preProject + .appveyor.yml = .appveyor.yml + .editorconfig = .editorconfig + .gitattributes = .gitattributes + .gitignore = .gitignore + .travis.yml = .travis.yml + build.cmd = build.cmd + build.ps1 = build.ps1 + build.sh = build.sh + CONTRIBUTING.md = CONTRIBUTING.md + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + LICENSE.txt = LICENSE.txt + NuGet.config = NuGet.config + NuGetPackageVerifier.json = NuGetPackageVerifier.json + README.md = README.md + Settings.StyleCop = Settings.StyleCop + version.xml = version.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{44546170-35BF-448F-88F5-4331AE67AEAE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers.Experimental.Test", "test\Microsoft.AspNetCore.Mvc.Analyzers.Experimental.Test\Microsoft.AspNetCore.Mvc.Analyzers.Experimental.Test.csproj", "{2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers", "src\Microsoft.AspNetCore.Mvc.Analyzers\Microsoft.AspNetCore.Mvc.Analyzers.csproj", "{30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers.Experimental", "src\Microsoft.AspNetCore.Mvc.Analyzers.Experimental\Microsoft.AspNetCore.Mvc.Analyzers.Experimental.csproj", "{F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers.Test", "test\Microsoft.AspNetCore.Mvc.Analyzers.Test\Microsoft.AspNetCore.Mvc.Analyzers.Test.csproj", "{829D9A67-2D07-4CE6-86C0-59F2549B0CFA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|x86.ActiveCfg = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|Any CPU.Build.0 = Release|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|x86.ActiveCfg = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|x86.ActiveCfg = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|Any CPU.Build.0 = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|x86.ActiveCfg = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|x86.ActiveCfg = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|Any CPU.Build.0 = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|x86.ActiveCfg = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|x86.ActiveCfg = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|Any CPU.Build.0 = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|x86.ActiveCfg = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|x86.ActiveCfg = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|Any CPU.Build.0 = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|x86.ActiveCfg = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|x86.ActiveCfg = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Any CPU.Build.0 = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|x86.ActiveCfg = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|x86.ActiveCfg = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|Any CPU.Build.0 = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|x86.ActiveCfg = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|x86.ActiveCfg = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Any CPU.Build.0 = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|x86.ActiveCfg = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|x86.ActiveCfg = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|Any CPU.Build.0 = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|x86.ActiveCfg = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|x86.ActiveCfg = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Any CPU.Build.0 = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|x86.ActiveCfg = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.ActiveCfg = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.Build.0 = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Any CPU.Build.0 = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|x86.ActiveCfg = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|x86.Build.0 = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|x86.ActiveCfg = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|x86.Build.0 = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|Any CPU.Build.0 = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|x86.ActiveCfg = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|x86.Build.0 = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|x86.ActiveCfg = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|x86.Build.0 = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|Any CPU.Build.0 = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|x86.ActiveCfg = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|x86.Build.0 = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|x86.ActiveCfg = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|x86.Build.0 = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|Any CPU.Build.0 = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|x86.ActiveCfg = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|x86.Build.0 = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|x86.Build.0 = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|Any CPU.Build.0 = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|x86.ActiveCfg = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|x86.Build.0 = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|x86.ActiveCfg = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|x86.Build.0 = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|Any CPU.Build.0 = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|x86.ActiveCfg = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|x86.Build.0 = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|x86.ActiveCfg = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|x86.Build.0 = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|Any CPU.Build.0 = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|x86.ActiveCfg = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|x86.Build.0 = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|x86.ActiveCfg = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|x86.Build.0 = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|Any CPU.Build.0 = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|x86.ActiveCfg = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|x86.Build.0 = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|x86.ActiveCfg = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|x86.Build.0 = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|Any CPU.Build.0 = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|x86.ActiveCfg = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|x86.Build.0 = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|Any CPU.Build.0 = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|x86.ActiveCfg = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|x86.Build.0 = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|Any CPU.ActiveCfg = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|Any CPU.Build.0 = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|x86.ActiveCfg = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|x86.Build.0 = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|x86.ActiveCfg = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|x86.Build.0 = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|Any CPU.Build.0 = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|x86.ActiveCfg = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|x86.Build.0 = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|x86.ActiveCfg = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|x86.Build.0 = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|Any CPU.Build.0 = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|x86.ActiveCfg = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|x86.Build.0 = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|x86.ActiveCfg = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|x86.Build.0 = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|Any CPU.Build.0 = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|x86.ActiveCfg = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|x86.Build.0 = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|x86.ActiveCfg = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|x86.Build.0 = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|Any CPU.Build.0 = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|x86.ActiveCfg = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|x86.Build.0 = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|x86.ActiveCfg = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|x86.Build.0 = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|Any CPU.Build.0 = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|x86.ActiveCfg = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|x86.Build.0 = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|x86.ActiveCfg = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|x86.Build.0 = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|Any CPU.Build.0 = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|x86.ActiveCfg = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|x86.Build.0 = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|x86.ActiveCfg = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|x86.Build.0 = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|Any CPU.Build.0 = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|x86.ActiveCfg = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|x86.Build.0 = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|x86.Build.0 = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|Any CPU.Build.0 = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|x86.ActiveCfg = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|x86.Build.0 = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|x86.ActiveCfg = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|x86.Build.0 = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|Any CPU.Build.0 = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|x86.ActiveCfg = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|x86.Build.0 = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|x86.ActiveCfg = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|x86.Build.0 = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|Any CPU.Build.0 = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|x86.ActiveCfg = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|x86.Build.0 = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|x86.ActiveCfg = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|x86.Build.0 = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|Any CPU.Build.0 = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|x86.ActiveCfg = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|x86.Build.0 = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|x86.ActiveCfg = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|x86.Build.0 = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|Any CPU.Build.0 = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|x86.ActiveCfg = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|x86.Build.0 = Release|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Debug|x86.ActiveCfg = Debug|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Debug|x86.Build.0 = Debug|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Release|Any CPU.Build.0 = Release|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Release|x86.ActiveCfg = Release|Any CPU + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35}.Release|x86.Build.0 = Release|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Debug|x86.ActiveCfg = Debug|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Debug|x86.Build.0 = Debug|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Release|Any CPU.Build.0 = Release|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Release|x86.ActiveCfg = Release|Any CPU + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD}.Release|x86.Build.0 = Release|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Debug|x86.ActiveCfg = Debug|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Debug|x86.Build.0 = Debug|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Release|Any CPU.Build.0 = Release|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Release|x86.ActiveCfg = Release|Any CPU + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3}.Release|x86.Build.0 = Release|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Debug|x86.ActiveCfg = Debug|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Debug|x86.Build.0 = Debug|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Release|Any CPU.Build.0 = Release|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Release|x86.ActiveCfg = Release|Any CPU + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754}.Release|x86.Build.0 = Release|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Debug|x86.ActiveCfg = Debug|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Debug|x86.Build.0 = Debug|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Release|Any CPU.Build.0 = Release|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Release|x86.ActiveCfg = Release|Any CPU + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {079EFA1F-0B0A-4853-B27B-5780D111CD85} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {3F6E355E-4869-41D9-943B-D54771221A7F} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {A8AA326E-8EE8-4F11-B750-23028E0949D7} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {5F945B82-FE5F-425C-956C-8BC2F2020254} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {5DE8E4D9-AACD-4B5F-819F-F091383FB996} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {B2347320-308E-4D2B-AEC8-005DFA68B0C9} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {860119ED-3DB1-424D-8D0A-30132A8A7D96} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {864FA09D-1E48-403A-A6C8-4F079D2A30F0} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {1154203C-7579-4525-906E-BC55268421C1} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {A2B72833-5D70-4C42-AE85-E0319926FB8A} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {DA000953-7532-4DF5-8DB9-8143DF98D999} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {3FC8D9D6-9352-43A3-8E81-422F270085B7} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {42C81540-CD47-4C68-A7A3-2A93B9C3B210} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {493780DA-E696-40FF-BD12-4A5C5736F292} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {22019146-BDFA-442E-8C8E-345FB9644578} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {2DD786CA-7AF7-437A-B499-801A589B9A1C} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {60873DFA-97B9-419E-BAA3-940FC9B07085} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {50893B10-5735-4F35-9995-F81DA3F0189E} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {14ED4476-9F24-4776-8417-EA6927F6C9C9} = {DAAE4C74-D06F-4874-A166-33305D2643CE} + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {0AB46520-F441-4E01-B444-08F4D23F8B1B} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {28D4DA20-6E13-47F9-80AE-D6AA7699CC35} = {44546170-35BF-448F-88F5-4331AE67AEAE} + {2E6CDE10-8F96-4B75-B0D9-808F6A01B8BD} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {30862895-C1FA-49F5-B69A-B0F9F2ECD0F3} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {F8FD2D6A-DCD1-4A7B-B599-B728A12A1754} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {829D9A67-2D07-4CE6-86C0-59F2549B0CFA} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D003597F-372F-4068-A2F0-353BE3C3B39A} + EndGlobalSection +EndGlobal diff --git a/src/Mvc/Mvc.sln b/src/Mvc/Mvc.sln new file mode 100644 index 0000000000..da45132198 --- /dev/null +++ b/src/Mvc/Mvc.sln @@ -0,0 +1,968 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2036 +MinimumVisualStudioVersion = 15.0.26730.03 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{32285FA4-6B46-4D6B-A840-2B13E4C8B58E}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}" + ProjectSection(SolutionItems) = preProject + test\Directory.Build.props = test\Directory.Build.props + test\MvcTests.ruleset = test\MvcTests.ruleset + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc", "src\Microsoft.AspNetCore.Mvc\Microsoft.AspNetCore.Mvc.csproj", "{079EFA1F-0B0A-4853-B27B-5780D111CD85}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor", "src\Microsoft.AspNetCore.Mvc.Razor\Microsoft.AspNetCore.Mvc.Razor.csproj", "{314E9AD6-2FFC-4A92-A8AD-510658C64F1E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Core", "src\Microsoft.AspNetCore.Mvc.Core\Microsoft.AspNetCore.Mvc.Core.csproj", "{C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Razor.Test", "test\Microsoft.AspNetCore.Mvc.Razor.Test\Microsoft.AspNetCore.Mvc.Razor.Test.csproj", "{3F6E355E-4869-41D9-943B-D54771221A7F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Core.Test", "test\Microsoft.AspNetCore.Mvc.Core.Test\Microsoft.AspNetCore.Mvc.Core.Test.csproj", "{A8AA326E-8EE8-4F11-B750-23028E0949D7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSites", "WebSites", "{16703B76-C9F7-4C75-AE6C-53D92E308E3C}" + ProjectSection(SolutionItems) = preProject + test\WebSites\Directory.Build.props = test\WebSites\Directory.Build.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.FunctionalTests", "test\Microsoft.AspNetCore.Mvc.FunctionalTests\Microsoft.AspNetCore.Mvc.FunctionalTests.csproj", "{323D0C04-B518-4A8F-8A8E-3546AD153D34}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicWebSite", "test\WebSites\BasicWebSite\BasicWebSite.csproj", "{34DF1487-12C6-476C-BE0A-F31DF1939AE5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoutingWebSite", "test\WebSites\RoutingWebSite\RoutingWebSite.csproj", "{42CDBF4A-E238-4C0F-A416-44588363EB4C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Test", "test\Microsoft.AspNetCore.Mvc.Test\Microsoft.AspNetCore.Mvc.Test.csproj", "{5F945B82-FE5F-425C-956C-8BC2F2020254}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorWebSite", "test\WebSites\RazorWebSite\RazorWebSite.csproj", "{B07CAF59-11ED-40E3-A5DB-E1178F84FA78}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FormatterWebSite", "test\WebSites\FormatterWebSite\FormatterWebSite.csproj", "{62735776-46FF-4170-9392-02E128A69B89}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiExplorerWebSite", "test\WebSites\ApiExplorerWebSite\ApiExplorerWebSite.csproj", "{61061528-071E-424E-965A-07BCC2F02672}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VersioningWebSite", "test\WebSites\VersioningWebSite\VersioningWebSite.csproj", "{C6304029-78C8-4604-99BE-2078DCA1DD36}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagHelpersWebSite", "test\WebSites\TagHelpersWebSite\TagHelpersWebSite.csproj", "{6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FilesWebSite", "test\WebSites\FilesWebSite\FilesWebSite.csproj", "{0EF9860B-10D7-452F-B0F4-A405B88BEBB3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPageExecutionInstrumentationWebSite", "test\WebSites\RazorPageExecutionInstrumentationWebSite\RazorPageExecutionInstrumentationWebSite.csproj", "{2B2B9876-903C-4065-8D62-2EE832BBA106}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplicationModelWebSite", "test\WebSites\ApplicationModelWebSite\ApplicationModelWebSite.csproj", "{CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.WebApiCompatShim", "src\Microsoft.AspNetCore.Mvc.WebApiCompatShim\Microsoft.AspNetCore.Mvc.WebApiCompatShim.csproj", "{23D30B8C-04B1-4577-A604-ED27EA1E4A0E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiCompatShimWebSite", "test\WebSites\WebApiCompatShimWebSite\WebApiCompatShimWebSite.csproj", "{B2B7BC91-688E-4C1E-A71F-CE948D958DDF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.WebApiCompatShimTest", "test\Microsoft.AspNetCore.Mvc.WebApiCompatShimTest\Microsoft.AspNetCore.Mvc.WebApiCompatShimTest.csproj", "{5DE8E4D9-AACD-4B5F-819F-F091383FB996}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TagHelpers", "src\Microsoft.AspNetCore.Mvc.TagHelpers\Microsoft.AspNetCore.Mvc.TagHelpers.csproj", "{B2347320-308E-4D2B-AEC8-005DFA68B0C9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TagHelpers.Test", "test\Microsoft.AspNetCore.Mvc.TagHelpers.Test\Microsoft.AspNetCore.Mvc.TagHelpers.Test.csproj", "{860119ED-3DB1-424D-8D0A-30132A8A7D96}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HtmlGenerationWebSite", "test\WebSites\HtmlGenerationWebSite\HtmlGenerationWebSite.csproj", "{920F8A0E-6F7D-4BBE-84FF-840B89099BE6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ErrorPageMiddlewareWebSite", "test\WebSites\ErrorPageMiddlewareWebSite\ErrorPageMiddlewareWebSite.csproj", "{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XmlFormattersWebSite", "test\WebSites\XmlFormattersWebSite\XmlFormattersWebSite.csproj", "{C3123A70-41C4-4122-AD1C-D35DF8958DD7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControllersFromServicesWebSite", "test\WebSites\ControllersFromServicesWebSite\ControllersFromServicesWebSite.csproj", "{983741B2-4424-4ED1-9B03-7675A67230C8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControllersFromServicesClassLibrary", "test\WebSites\ControllersFromServicesClassLibrary\ControllersFromServicesClassLibrary.csproj", "{551DC89E-2A13-4CF2-83D7-1ADD802443D5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TestCommon", "test\Microsoft.AspNetCore.Mvc.TestCommon\Microsoft.AspNetCore.Mvc.TestCommon.csproj", "{F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CorsWebSite", "test\WebSites\CorsWebSite\CorsWebSite.csproj", "{94BA134D-04B3-48AA-BA55-5A4DB8640F2D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.IntegrationTests", "test\Microsoft.AspNetCore.Mvc.IntegrationTests\Microsoft.AspNetCore.Mvc.IntegrationTests.csproj", "{864FA09D-1E48-403A-A6C8-4F079D2A30F0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Abstractions", "src\Microsoft.AspNetCore.Mvc.Abstractions\Microsoft.AspNetCore.Mvc.Abstractions.csproj", "{1154203C-7579-4525-906E-BC55268421C1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ApiExplorer", "src\Microsoft.AspNetCore.Mvc.ApiExplorer\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj", "{A2B72833-5D70-4C42-AE85-E0319926FB8A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ApiExplorer.Test", "test\Microsoft.AspNetCore.Mvc.ApiExplorer.Test\Microsoft.AspNetCore.Mvc.ApiExplorer.Test.csproj", "{4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Abstractions.Test", "test\Microsoft.AspNetCore.Mvc.Abstractions.Test\Microsoft.AspNetCore.Mvc.Abstractions.Test.csproj", "{DA000953-7532-4DF5-8DB9-8143DF98D999}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ViewFeatures", "src\Microsoft.AspNetCore.Mvc.ViewFeatures\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj", "{3F8B8FC1-9FE4-4788-8991-367113E8D7AD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Formatters.Json", "src\Microsoft.AspNetCore.Mvc.Formatters.Json\Microsoft.AspNetCore.Mvc.Formatters.Json.csproj", "{3FC8D9D6-9352-43A3-8E81-422F270085B7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Formatters.Xml", "src\Microsoft.AspNetCore.Mvc.Formatters.Xml\Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj", "{42C81540-CD47-4C68-A7A3-2A93B9C3B210}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Formatters.Json.Test", "test\Microsoft.AspNetCore.Mvc.Formatters.Json.Test\Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj", "{493780DA-E696-40FF-BD12-4A5C5736F292}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Formatters.Xml.Test", "test\Microsoft.AspNetCore.Mvc.Formatters.Xml.Test\Microsoft.AspNetCore.Mvc.Formatters.Xml.Test.csproj", "{22019146-BDFA-442E-8C8E-345FB9644578}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Cors", "src\Microsoft.AspNetCore.Mvc.Cors\Microsoft.AspNetCore.Mvc.Cors.csproj", "{9A07EEA2-942E-4969-9D41-799B6E2D1FF5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.DataAnnotations", "src\Microsoft.AspNetCore.Mvc.DataAnnotations\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj", "{2DD786CA-7AF7-437A-B499-801A589B9A1C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Cors.Test", "test\Microsoft.AspNetCore.Mvc.Cors.Test\Microsoft.AspNetCore.Mvc.Cors.Test.csproj", "{6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.DataAnnotations.Test", "test\Microsoft.AspNetCore.Mvc.DataAnnotations.Test\Microsoft.AspNetCore.Mvc.DataAnnotations.Test.csproj", "{827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.ViewFeatures.Test", "test\Microsoft.AspNetCore.Mvc.ViewFeatures.Test\Microsoft.AspNetCore.Mvc.ViewFeatures.Test.csproj", "{60873DFA-97B9-419E-BAA3-940FC9B07085}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Localization", "src\Microsoft.AspNetCore.Mvc.Localization\Microsoft.AspNetCore.Mvc.Localization.csproj", "{50893B10-5735-4F35-9995-F81DA3F0189E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Localization.Test", "test\Microsoft.AspNetCore.Mvc.Localization.Test\Microsoft.AspNetCore.Mvc.Localization.Test.csproj", "{8FC726B5-E766-44E0-8B38-1313B6D8D9A7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.TestDiagnosticListener", "test\Microsoft.AspNetCore.Mvc.TestDiagnosticListener\Microsoft.AspNetCore.Mvc.TestDiagnosticListener.csproj", "{9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MvcSandbox", "samples\MvcSandbox\MvcSandbox.csproj", "{14ED4476-9F24-4776-8417-EA6927F6C9C9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleWebSite", "test\WebSites\SimpleWebSite\SimpleWebSite.csproj", "{396B40D7-AC70-49A7-B33C-ED42129FEBE3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityWebSite", "test\WebSites\SecurityWebSite\SecurityWebSite.csproj", "{D28CAC79-7004-4B69-993B-EDEB4653BFA8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.RazorPages", "src\Microsoft.AspNetCore.Mvc.RazorPages\Microsoft.AspNetCore.Mvc.RazorPages.csproj", "{CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.RazorPages.Test", "test\Microsoft.AspNetCore.Mvc.RazorPages.Test\Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj", "{0AB46520-F441-4E01-B444-08F4D23F8B1B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPagesWebSite", "test\WebSites\RazorPagesWebSite\RazorPagesWebSite.csproj", "{4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Performance", "benchmarks\Microsoft.AspNetCore.Mvc.Performance\Microsoft.AspNetCore.Mvc.Performance.csproj", "{F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Testing", "src\Microsoft.AspNetCore.Mvc.Testing\Microsoft.AspNetCore.Mvc.Testing.csproj", "{7500B228-1769-4CFB-A571-3DFAC6678A06}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{631720EE-11CC-41C9-9819-441417ECBEAA}" + ProjectSection(SolutionItems) = preProject + .appveyor.yml = .appveyor.yml + .editorconfig = .editorconfig + .gitattributes = .gitattributes + .gitignore = .gitignore + .travis.yml = .travis.yml + build.cmd = build.cmd + build.ps1 = build.ps1 + build.sh = build.sh + CONTRIBUTING.md = CONTRIBUTING.md + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets + LICENSE.txt = LICENSE.txt + NuGet.config = NuGet.config + NuGetPackageVerifier.json = NuGetPackageVerifier.json + README.md = README.md + Settings.StyleCop = Settings.StyleCop + version.xml = version.xml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{FDC66952-A3EA-4074-899E-C29816BF7C1F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorBuildWebSite", "test\WebSites\RazorBuildWebSite\RazorBuildWebSite.csproj", "{BF8A3392-C3D2-4813-855A-E906564600E1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorBuildWebSite.PrecompiledViews", "test\WebSites\RazorBuildWebSite.PrecompiledViews\RazorBuildWebSite.PrecompiledViews.csproj", "{856D7E25-E033-477D-9ABD-0B50CF428C80}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorBuildWebSite.Views", "test\WebSites\RazorBuildWebSite.Views\RazorBuildWebSite.Views.csproj", "{8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers", "src\Microsoft.AspNetCore.Mvc.Analyzers\Microsoft.AspNetCore.Mvc.Analyzers.csproj", "{87A3E227-C45E-4141-A59F-402908E651FD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers.Test", "test\Microsoft.AspNetCore.Mvc.Analyzers.Test\Microsoft.AspNetCore.Mvc.Analyzers.Test.csproj", "{E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers.Experimental", "src\Microsoft.AspNetCore.Mvc.Analyzers.Experimental\Microsoft.AspNetCore.Mvc.Analyzers.Experimental.csproj", "{CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Analyzers.Experimental.Test", "test\Microsoft.AspNetCore.Mvc.Analyzers.Experimental.Test\Microsoft.AspNetCore.Mvc.Analyzers.Experimental.Test.csproj", "{E83D3745-9BCF-40E8-8D34-AFBA604C2439}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorPagesClassLibrary", "test\WebSites\RazorPagesClassLibrary\RazorPagesClassLibrary.csproj", "{17122147-ADFD-41C8-87D9-CCC582CCA8F9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Debug|x86.ActiveCfg = Debug|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|Any CPU.Build.0 = Release|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {079EFA1F-0B0A-4853-B27B-5780D111CD85}.Release|x86.ActiveCfg = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Debug|x86.ActiveCfg = Debug|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|Any CPU.Build.0 = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E}.Release|x86.ActiveCfg = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Debug|x86.ActiveCfg = Debug|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|Any CPU.Build.0 = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF}.Release|x86.ActiveCfg = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Debug|x86.ActiveCfg = Debug|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|Any CPU.Build.0 = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3F6E355E-4869-41D9-943B-D54771221A7F}.Release|x86.ActiveCfg = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Debug|x86.ActiveCfg = Debug|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|Any CPU.Build.0 = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A8AA326E-8EE8-4F11-B750-23028E0949D7}.Release|x86.ActiveCfg = Release|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Debug|Any CPU.Build.0 = Debug|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Debug|x86.ActiveCfg = Debug|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Release|Any CPU.ActiveCfg = Release|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Release|Any CPU.Build.0 = Release|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {323D0C04-B518-4A8F-8A8E-3546AD153D34}.Release|x86.ActiveCfg = Release|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Debug|x86.ActiveCfg = Debug|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|Any CPU.Build.0 = Release|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|x86.ActiveCfg = Release|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|x86.ActiveCfg = Debug|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|Any CPU.Build.0 = Release|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|x86.ActiveCfg = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Debug|x86.ActiveCfg = Debug|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Any CPU.Build.0 = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|x86.ActiveCfg = Release|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Debug|x86.ActiveCfg = Debug|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Release|Any CPU.Build.0 = Release|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Release|x86.ActiveCfg = Release|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Debug|x86.ActiveCfg = Debug|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Release|Any CPU.Build.0 = Release|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {62735776-46FF-4170-9392-02E128A69B89}.Release|x86.ActiveCfg = Release|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Debug|x86.ActiveCfg = Debug|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Release|Any CPU.Build.0 = Release|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {61061528-071E-424E-965A-07BCC2F02672}.Release|x86.ActiveCfg = Release|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Debug|x86.ActiveCfg = Debug|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Release|Any CPU.Build.0 = Release|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C6304029-78C8-4604-99BE-2078DCA1DD36}.Release|x86.ActiveCfg = Release|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Debug|x86.ActiveCfg = Debug|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Release|Any CPU.Build.0 = Release|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47}.Release|x86.ActiveCfg = Release|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Debug|x86.ActiveCfg = Debug|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Release|Any CPU.Build.0 = Release|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3}.Release|x86.ActiveCfg = Release|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Debug|x86.ActiveCfg = Debug|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Release|Any CPU.Build.0 = Release|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2B2B9876-903C-4065-8D62-2EE832BBA106}.Release|x86.ActiveCfg = Release|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Debug|x86.ActiveCfg = Debug|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Release|Any CPU.Build.0 = Release|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657}.Release|x86.ActiveCfg = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Debug|x86.ActiveCfg = Debug|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|Any CPU.Build.0 = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E}.Release|x86.ActiveCfg = Release|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Debug|x86.ActiveCfg = Debug|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Release|Any CPU.Build.0 = Release|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF}.Release|x86.ActiveCfg = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Debug|x86.ActiveCfg = Debug|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Any CPU.Build.0 = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|x86.ActiveCfg = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Debug|x86.ActiveCfg = Debug|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|Any CPU.Build.0 = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B2347320-308E-4D2B-AEC8-005DFA68B0C9}.Release|x86.ActiveCfg = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Debug|x86.ActiveCfg = Debug|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Any CPU.Build.0 = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {860119ED-3DB1-424D-8D0A-30132A8A7D96}.Release|x86.ActiveCfg = Release|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|x86.ActiveCfg = Debug|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Debug|x86.Build.0 = Debug|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Release|Any CPU.Build.0 = Release|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Release|x86.ActiveCfg = Release|Any CPU + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6}.Release|x86.Build.0 = Release|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|x86.ActiveCfg = Debug|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|x86.Build.0 = Debug|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|Any CPU.Build.0 = Release|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|x86.ActiveCfg = Release|Any CPU + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|x86.Build.0 = Release|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Debug|x86.ActiveCfg = Debug|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Debug|x86.Build.0 = Debug|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Release|Any CPU.Build.0 = Release|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Release|x86.ActiveCfg = Release|Any CPU + {C3123A70-41C4-4122-AD1C-D35DF8958DD7}.Release|x86.Build.0 = Release|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Debug|x86.ActiveCfg = Debug|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Debug|x86.Build.0 = Debug|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Release|Any CPU.Build.0 = Release|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Release|x86.ActiveCfg = Release|Any CPU + {983741B2-4424-4ED1-9B03-7675A67230C8}.Release|x86.Build.0 = Release|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Debug|x86.ActiveCfg = Debug|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Debug|x86.Build.0 = Debug|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|Any CPU.Build.0 = Release|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|x86.ActiveCfg = Release|Any CPU + {551DC89E-2A13-4CF2-83D7-1ADD802443D5}.Release|x86.Build.0 = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.ActiveCfg = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Debug|x86.Build.0 = Debug|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Any CPU.Build.0 = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|x86.ActiveCfg = Release|Any CPU + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5}.Release|x86.Build.0 = Release|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Debug|x86.ActiveCfg = Debug|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Debug|x86.Build.0 = Debug|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Release|Any CPU.Build.0 = Release|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Release|x86.ActiveCfg = Release|Any CPU + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D}.Release|x86.Build.0 = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|x86.ActiveCfg = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Debug|x86.Build.0 = Debug|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|Any CPU.Build.0 = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|x86.ActiveCfg = Release|Any CPU + {864FA09D-1E48-403A-A6C8-4F079D2A30F0}.Release|x86.Build.0 = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|x86.ActiveCfg = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Debug|x86.Build.0 = Debug|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|Any CPU.Build.0 = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|x86.ActiveCfg = Release|Any CPU + {1154203C-7579-4525-906E-BC55268421C1}.Release|x86.Build.0 = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|x86.ActiveCfg = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Debug|x86.Build.0 = Debug|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|Any CPU.Build.0 = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|x86.ActiveCfg = Release|Any CPU + {A2B72833-5D70-4C42-AE85-E0319926FB8A}.Release|x86.Build.0 = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Debug|x86.Build.0 = Debug|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|Any CPU.Build.0 = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|x86.ActiveCfg = Release|Any CPU + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6}.Release|x86.Build.0 = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|x86.ActiveCfg = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Debug|x86.Build.0 = Debug|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|Any CPU.Build.0 = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|x86.ActiveCfg = Release|Any CPU + {DA000953-7532-4DF5-8DB9-8143DF98D999}.Release|x86.Build.0 = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|x86.ActiveCfg = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Debug|x86.Build.0 = Debug|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|Any CPU.Build.0 = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|x86.ActiveCfg = Release|Any CPU + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD}.Release|x86.Build.0 = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|x86.ActiveCfg = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Debug|x86.Build.0 = Debug|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|Any CPU.Build.0 = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|x86.ActiveCfg = Release|Any CPU + {3FC8D9D6-9352-43A3-8E81-422F270085B7}.Release|x86.Build.0 = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|x86.ActiveCfg = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Debug|x86.Build.0 = Debug|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|Any CPU.Build.0 = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|x86.ActiveCfg = Release|Any CPU + {42C81540-CD47-4C68-A7A3-2A93B9C3B210}.Release|x86.Build.0 = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|Any CPU.Build.0 = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|x86.ActiveCfg = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Debug|x86.Build.0 = Debug|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|Any CPU.ActiveCfg = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|Any CPU.Build.0 = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|x86.ActiveCfg = Release|Any CPU + {493780DA-E696-40FF-BD12-4A5C5736F292}.Release|x86.Build.0 = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|x86.ActiveCfg = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Debug|x86.Build.0 = Debug|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|Any CPU.Build.0 = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|x86.ActiveCfg = Release|Any CPU + {22019146-BDFA-442E-8C8E-345FB9644578}.Release|x86.Build.0 = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|x86.ActiveCfg = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Debug|x86.Build.0 = Debug|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|Any CPU.Build.0 = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|x86.ActiveCfg = Release|Any CPU + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5}.Release|x86.Build.0 = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|x86.ActiveCfg = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Debug|x86.Build.0 = Debug|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|Any CPU.Build.0 = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|x86.ActiveCfg = Release|Any CPU + {2DD786CA-7AF7-437A-B499-801A589B9A1C}.Release|x86.Build.0 = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|x86.ActiveCfg = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Debug|x86.Build.0 = Debug|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|Any CPU.Build.0 = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|x86.ActiveCfg = Release|Any CPU + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5}.Release|x86.Build.0 = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|x86.ActiveCfg = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Debug|x86.Build.0 = Debug|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|Any CPU.Build.0 = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|x86.ActiveCfg = Release|Any CPU + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B}.Release|x86.Build.0 = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|x86.ActiveCfg = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Debug|x86.Build.0 = Debug|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|Any CPU.Build.0 = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|x86.ActiveCfg = Release|Any CPU + {60873DFA-97B9-419E-BAA3-940FC9B07085}.Release|x86.Build.0 = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|x86.ActiveCfg = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Debug|x86.Build.0 = Debug|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|Any CPU.Build.0 = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|x86.ActiveCfg = Release|Any CPU + {50893B10-5735-4F35-9995-F81DA3F0189E}.Release|x86.Build.0 = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Debug|x86.Build.0 = Debug|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|Any CPU.Build.0 = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|x86.ActiveCfg = Release|Any CPU + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7}.Release|x86.Build.0 = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|x86.ActiveCfg = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Debug|x86.Build.0 = Debug|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|Any CPU.Build.0 = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|x86.ActiveCfg = Release|Any CPU + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4}.Release|x86.Build.0 = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|x86.ActiveCfg = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Debug|x86.Build.0 = Debug|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|Any CPU.Build.0 = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|x86.ActiveCfg = Release|Any CPU + {14ED4476-9F24-4776-8417-EA6927F6C9C9}.Release|x86.Build.0 = Release|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Debug|x86.ActiveCfg = Debug|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Debug|x86.Build.0 = Debug|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Release|Any CPU.Build.0 = Release|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Release|x86.ActiveCfg = Release|Any CPU + {396B40D7-AC70-49A7-B33C-ED42129FEBE3}.Release|x86.Build.0 = Release|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Debug|x86.ActiveCfg = Debug|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Debug|x86.Build.0 = Debug|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Release|Any CPU.Build.0 = Release|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Release|x86.ActiveCfg = Release|Any CPU + {D28CAC79-7004-4B69-993B-EDEB4653BFA8}.Release|x86.Build.0 = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|x86.ActiveCfg = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Debug|x86.Build.0 = Debug|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|Any CPU.Build.0 = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|x86.ActiveCfg = Release|Any CPU + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53}.Release|x86.Build.0 = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|x86.ActiveCfg = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Debug|x86.Build.0 = Debug|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|Any CPU.Build.0 = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|x86.ActiveCfg = Release|Any CPU + {0AB46520-F441-4E01-B444-08F4D23F8B1B}.Release|x86.Build.0 = Release|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Debug|x86.ActiveCfg = Debug|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Debug|x86.Build.0 = Debug|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Release|Any CPU.Build.0 = Release|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Release|x86.ActiveCfg = Release|Any CPU + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352}.Release|x86.Build.0 = Release|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Debug|x86.ActiveCfg = Debug|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Debug|x86.Build.0 = Debug|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Release|Any CPU.Build.0 = Release|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Release|x86.ActiveCfg = Release|Any CPU + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE}.Release|x86.Build.0 = Release|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Debug|x86.ActiveCfg = Debug|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Debug|x86.Build.0 = Debug|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Release|Any CPU.Build.0 = Release|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Release|x86.ActiveCfg = Release|Any CPU + {7500B228-1769-4CFB-A571-3DFAC6678A06}.Release|x86.Build.0 = Release|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Debug|x86.ActiveCfg = Debug|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Debug|x86.Build.0 = Debug|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Release|Any CPU.Build.0 = Release|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Release|x86.ActiveCfg = Release|Any CPU + {BF8A3392-C3D2-4813-855A-E906564600E1}.Release|x86.Build.0 = Release|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Debug|x86.ActiveCfg = Debug|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Debug|x86.Build.0 = Debug|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Release|Any CPU.Build.0 = Release|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Release|x86.ActiveCfg = Release|Any CPU + {856D7E25-E033-477D-9ABD-0B50CF428C80}.Release|x86.Build.0 = Release|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Debug|x86.ActiveCfg = Debug|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Debug|x86.Build.0 = Debug|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Release|Any CPU.Build.0 = Release|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Release|x86.ActiveCfg = Release|Any CPU + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A}.Release|x86.Build.0 = Release|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Debug|x86.ActiveCfg = Debug|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Debug|x86.Build.0 = Debug|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Release|Any CPU.Build.0 = Release|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Release|x86.ActiveCfg = Release|Any CPU + {87A3E227-C45E-4141-A59F-402908E651FD}.Release|x86.Build.0 = Release|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Debug|x86.ActiveCfg = Debug|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Debug|x86.Build.0 = Debug|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Release|Any CPU.Build.0 = Release|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Release|x86.ActiveCfg = Release|Any CPU + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831}.Release|x86.Build.0 = Release|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Debug|x86.ActiveCfg = Debug|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Debug|x86.Build.0 = Debug|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Release|Any CPU.Build.0 = Release|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Release|x86.ActiveCfg = Release|Any CPU + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61}.Release|x86.Build.0 = Release|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Debug|x86.ActiveCfg = Debug|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Debug|x86.Build.0 = Debug|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Release|Any CPU.Build.0 = Release|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Release|x86.ActiveCfg = Release|Any CPU + {E83D3745-9BCF-40E8-8D34-AFBA604C2439}.Release|x86.Build.0 = Release|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Debug|x86.ActiveCfg = Debug|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Debug|x86.Build.0 = Debug|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Release|Any CPU.Build.0 = Release|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Release|x86.ActiveCfg = Release|Any CPU + {17122147-ADFD-41C8-87D9-CCC582CCA8F9}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {079EFA1F-0B0A-4853-B27B-5780D111CD85} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {314E9AD6-2FFC-4A92-A8AD-510658C64F1E} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {C48DA9D7-ACB5-4408-AA79-27ECB60A67EF} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {3F6E355E-4869-41D9-943B-D54771221A7F} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {A8AA326E-8EE8-4F11-B750-23028E0949D7} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {16703B76-C9F7-4C75-AE6C-53D92E308E3C} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {323D0C04-B518-4A8F-8A8E-3546AD153D34} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {34DF1487-12C6-476C-BE0A-F31DF1939AE5} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {42CDBF4A-E238-4C0F-A416-44588363EB4C} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {5F945B82-FE5F-425C-956C-8BC2F2020254} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {B07CAF59-11ED-40E3-A5DB-E1178F84FA78} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {62735776-46FF-4170-9392-02E128A69B89} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {61061528-071E-424E-965A-07BCC2F02672} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {C6304029-78C8-4604-99BE-2078DCA1DD36} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {0EF9860B-10D7-452F-B0F4-A405B88BEBB3} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {2B2B9876-903C-4065-8D62-2EE832BBA106} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {CAE52CB7-0FAC-4B5B-8251-B0FF837DB657} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {23D30B8C-04B1-4577-A604-ED27EA1E4A0E} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {B2B7BC91-688E-4C1E-A71F-CE948D958DDF} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {5DE8E4D9-AACD-4B5F-819F-F091383FB996} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {B2347320-308E-4D2B-AEC8-005DFA68B0C9} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {860119ED-3DB1-424D-8D0A-30132A8A7D96} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {920F8A0E-6F7D-4BBE-84FF-840B89099BE6} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {AD545A5B-2BA5-4314-88AC-FC2ACF2CC718} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {C3123A70-41C4-4122-AD1C-D35DF8958DD7} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {983741B2-4424-4ED1-9B03-7675A67230C8} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {551DC89E-2A13-4CF2-83D7-1ADD802443D5} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {F504357E-C2E1-4818-BA5C-9A2EAC25FEE5} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {94BA134D-04B3-48AA-BA55-5A4DB8640F2D} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {864FA09D-1E48-403A-A6C8-4F079D2A30F0} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {1154203C-7579-4525-906E-BC55268421C1} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {A2B72833-5D70-4C42-AE85-E0319926FB8A} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {4C2AD8AB-8AC0-46C4-80C6-C5577C7255F6} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {DA000953-7532-4DF5-8DB9-8143DF98D999} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {3F8B8FC1-9FE4-4788-8991-367113E8D7AD} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {3FC8D9D6-9352-43A3-8E81-422F270085B7} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {42C81540-CD47-4C68-A7A3-2A93B9C3B210} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {493780DA-E696-40FF-BD12-4A5C5736F292} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {22019146-BDFA-442E-8C8E-345FB9644578} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {9A07EEA2-942E-4969-9D41-799B6E2D1FF5} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {2DD786CA-7AF7-437A-B499-801A589B9A1C} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {6BB4C20B-24C0-45D6-9E4C-C2620959BDD5} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {827DBBCB-F3A9-4BAD-8262-4BD43E28EB3B} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {60873DFA-97B9-419E-BAA3-940FC9B07085} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {50893B10-5735-4F35-9995-F81DA3F0189E} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {8FC726B5-E766-44E0-8B38-1313B6D8D9A7} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {9879B5D5-2325-4A81-B4DF-F279FE8FEEB4} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {14ED4476-9F24-4776-8417-EA6927F6C9C9} = {DAAE4C74-D06F-4874-A166-33305D2643CE} + {396B40D7-AC70-49A7-B33C-ED42129FEBE3} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {D28CAC79-7004-4B69-993B-EDEB4653BFA8} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {CF322BE1-E1FE-4CFD-8FCA-16A14B905D53} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {0AB46520-F441-4E01-B444-08F4D23F8B1B} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {4BA6EC9A-B6D9-41F2-BFDA-D82B22D80352} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {F16CEE0D-A28E-43BD-802F-99BAFE4BA7CE} = {FDC66952-A3EA-4074-899E-C29816BF7C1F} + {7500B228-1769-4CFB-A571-3DFAC6678A06} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {BF8A3392-C3D2-4813-855A-E906564600E1} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {856D7E25-E033-477D-9ABD-0B50CF428C80} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {8916DDCA-EC2A-4193-B9F3-78CAA1A96D5A} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + {87A3E227-C45E-4141-A59F-402908E651FD} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {E3E09D2F-1FCF-4396-9B09-5A62CA8CC831} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {CBF23034-2249-4FE5-BD48-5F3CEAC0DF61} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E} + {E83D3745-9BCF-40E8-8D34-AFBA604C2439} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {17122147-ADFD-41C8-87D9-CCC582CCA8F9} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {63D344F6-F86D-40E6-85B9-0AABBE338C4A} + EndGlobalSection +EndGlobal diff --git a/src/Mvc/NuGetPackageVerifier.json b/src/Mvc/NuGetPackageVerifier.json new file mode 100644 index 0000000000..b153ab1515 --- /dev/null +++ b/src/Mvc/NuGetPackageVerifier.json @@ -0,0 +1,7 @@ +{ + "Default": { + "rules": [ + "DefaultCompositeRule" + ] + } +} \ No newline at end of file diff --git a/src/Mvc/README.md b/src/Mvc/README.md new file mode 100644 index 0000000000..e5aa14d771 --- /dev/null +++ b/src/Mvc/README.md @@ -0,0 +1,28 @@ +ASP.NET Core MVC +=== + +**Note: For ASP.NET MVC 5.x, Web API 2.x, and Web Pages 3.x (not ASP.NET Core), see https://github.com/aspnet/AspNetWebStack** + +AppVeyor: [](https://ci.appveyor.com/project/aspnetci/mvc/branch/dev) + +Travis: [](https://travis-ci.org/aspnet/Mvc) + +ASP.NET Core MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development. ASP.NET Core MVC includes many features that enable fast, TDD-friendly development for creating sophisticated applications that use the latest web standards. + +ASP.NET Core MVC includes support for building web pages and HTTP services in a single aligned framework that can be hosted in IIS or self-hosted in your own process. + +See the [ASP.NET Core MVC documentation](https://docs.microsoft.com/aspnet/core/). + +Related community projects: +* [AspNet.Mvc.TypedRouting](https://github.com/ivaylokenov/AspNet.Mvc.TypedRouting): A collection of extension methods providing strongly typed routing and link generation for ASP.NET Core MVC projects. +* [ASP.NET MVC Boilerplate](https://visualstudiogallery.msdn.microsoft.com/6cf50a48-fc1e-4eaf-9e82-0b2a6705ca7d): Rich templates for ASP.NET Core MVC. +* [MyTested.AspNetCore.Mvc](https://github.com/ivaylokenov/MyTested.AspNetCore.Mvc): Powerful fluent testing framework for ASP.NET Core MVC. +* [MvcDeviceDetector](https://github.com/laskoviymishka/MvcDeviceDetector): Device detection mechanism to create mobile web applications. +* [XmlResult](https://github.com/Wallsmedia/XmlResult): XML formatter extensions to allow defining the XML serializer type. +* [AspNetCoreImageTagHelper](https://github.com/ignatandrei/AspNetCoreImageTagHelper): Tag helper for rendering images as inline base64 data. + +This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo. + +## Building from source + +To run a complete build on command line only, execute `build.cmd` or `build.sh` without arguments. See [developer documentation](https://github.com/aspnet/Home/wiki) for more details. diff --git a/src/Mvc/Settings.StyleCop b/src/Mvc/Settings.StyleCop new file mode 100644 index 0000000000..7b8130298c --- /dev/null +++ b/src/Mvc/Settings.StyleCop @@ -0,0 +1,455 @@ + + + NoMerge + + + + + False + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + as + db + dc + do + ef + id + if + in + is + my + no + on + sl + to + ui + vs + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + True + True + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + + + False + + + + + False + + + + + + + + + Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + + + + + + 120 + + + + \ No newline at end of file diff --git a/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/ActionSelectorBenchmark.cs b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/ActionSelectorBenchmark.cs new file mode 100644 index 0000000000..ec9c2c5a4b --- /dev/null +++ b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/ActionSelectorBenchmark.cs @@ -0,0 +1,264 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.ActionConstraints; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Mvc.Internal; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Microsoft.AspNetCore.Mvc.Performance +{ + public class ActionSelectorBenchmark + { + private const int Seed = 1000; + + // About 35 or so plausible sounding conventional routing actions. + // + // We include some duplicates here, because that's what happens when you have one method that handles + // GET and one that handles POST. + private static readonly ActionDescriptor[] _actions = new ActionDescriptor[] + { + CreateActionDescriptor(new { area = "Admin", controller = "Account", action = "AddUser" }), + CreateActionDescriptor(new { area = "Admin", controller = "Account", action = "AddUser" }), + CreateActionDescriptor(new { area = "Admin", controller = "Account", action = "DeleteUser" }), + CreateActionDescriptor(new { area = "Admin", controller = "Account", action = "DeleteUser" }), + CreateActionDescriptor(new { area = "Admin", controller = "Account", action = "Details" }), + CreateActionDescriptor(new { area = "Admin", controller = "Account", action = "List" }), + + CreateActionDescriptor(new { area = "Admin", controller = "Diagnostics", action = "Stats" }), + CreateActionDescriptor(new { area = "Admin", controller = "Diagnostics", action = "Performance" }), + + CreateActionDescriptor(new { area = "Admin", controller = "Products", action = "CreateProduct" }), + CreateActionDescriptor(new { area = "Admin", controller = "Products", action = "CreateProduct" }), + CreateActionDescriptor(new { area = "Admin", controller = "Products", action = "DeleteProduct" }), + CreateActionDescriptor(new { area = "Admin", controller = "Products", action = "DeleteProduct" }), + CreateActionDescriptor(new { area = "Admin", controller = "Products", action = "EditProduct" }), + CreateActionDescriptor(new { area = "Admin", controller = "Products", action = "EditProduct" }), + CreateActionDescriptor(new { area = "Admin", controller = "Products", action = "Index" }), + CreateActionDescriptor(new { area = "Admin", controller = "Products", action = "Inventory" }), + + CreateActionDescriptor(new { area = "Store", controller = "Search", action = "FindProduct" }), + CreateActionDescriptor(new { area = "Store", controller = "Search", action = "ShowCategory" }), + CreateActionDescriptor(new { area = "Store", controller = "Search", action = "HotItems" }), + + CreateActionDescriptor(new { area = "Store", controller = "Product", action = "Index" }), + CreateActionDescriptor(new { area = "Store", controller = "Product", action = "Details" }), + CreateActionDescriptor(new { area = "Store", controller = "Product", action = "Buy" }), + + CreateActionDescriptor(new { area = "Store", controller = "Checkout", action = "ViewCart" }), + CreateActionDescriptor(new { area = "Store", controller = "Checkout", action = "Billing" }), + CreateActionDescriptor(new { area = "Store", controller = "Checkout", action = "Confim" }), + CreateActionDescriptor(new { area = "Store", controller = "Checkout", action = "Confim" }), + + CreateActionDescriptor(new { area = "", controller = "Blog", action = "Index" }), + CreateActionDescriptor(new { area = "", controller = "Blog", action = "Search" }), + CreateActionDescriptor(new { area = "", controller = "Blog", action = "ViewPost" }), + CreateActionDescriptor(new { area = "", controller = "Blog", action = "PostComment" }), + + CreateActionDescriptor(new { area = "", controller = "Home", action = "Index" }), + CreateActionDescriptor(new { area = "", controller = "Home", action = "Search" }), + CreateActionDescriptor(new { area = "", controller = "Home", action = "About" }), + CreateActionDescriptor(new { area = "", controller = "Home", action = "Contact" }), + CreateActionDescriptor(new { area = "", controller = "Home", action = "Support" }), + }; + + private static readonly KeyValuePair>[] _dataSet = GetDataSet(_actions); + + private static readonly IActionSelector _actionSelector = CreateActionSelector(_actions); + + [Benchmark(Description = "conventional action selection implementation")] + public void SelectCandidates_MatchRouteData() + { + var routeContext = new RouteContext(new DefaultHttpContext()); + + for (var i = 0; i < _dataSet.Length; i++) + { + var routeValues = _dataSet[i].Key; + var expected = _dataSet[i].Value; + + var state = routeContext.RouteData.PushState(MockRouter.Instance, routeValues, null); + + var actual = _actionSelector.SelectCandidates(routeContext); + Verify(expected, actual); + + state.Restore(); + } + } + + [Benchmark(Baseline = true, Description = "conventional action selection baseline")] + public void SelectCandidates_Baseline() + { + var routeContext = new RouteContext(new DefaultHttpContext()); + + for (var i = 0; i < _dataSet.Length; i++) + { + var routeValues = _dataSet[i].Key; + var expected = _dataSet[i].Value; + + var state = routeContext.RouteData.PushState(MockRouter.Instance, routeValues, null); + + var actual = NaiveSelectCandiates(_actions, routeContext.RouteData.Values); + Verify(expected, actual); + + state.Restore(); + } + } + + // A naive implementation we can use to generate match data for inputs, and for a baseline. + private static IReadOnlyList NaiveSelectCandiates(ActionDescriptor[] actions, RouteValueDictionary routeValues) + { + var results = new List(); + for (var i = 0; i < actions.Length; i++) + { + var action = actions[i]; + + var isMatch = true; + foreach (var kvp in action.RouteValues) + { + var routeValue = Convert.ToString(routeValues[kvp.Key]) ?? string.Empty; + + if (string.IsNullOrEmpty(kvp.Value) && string.IsNullOrEmpty(routeValue)) + { + // Match + } + else if (string.Equals(kvp.Value, routeValue, StringComparison.OrdinalIgnoreCase)) + { + // Match; + } + else + { + isMatch = false; + break; + } + } + + if (isMatch) + { + results.Add(action); + } + } + + return results; + } + + private static ActionDescriptor CreateActionDescriptor(object obj) + { + // Our real ActionDescriptors don't use RVD, they use a regular old dictionary. + // Just using RVD here to understand the anonymous object for brevity. + var routeValues = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var kvp in new RouteValueDictionary(obj)) + { + routeValues.Add(kvp.Key, Convert.ToString(kvp.Value) ?? string.Empty); + } + + return new ActionDescriptor() + { + RouteValues = routeValues, + }; + } + + private static KeyValuePair>[] GetDataSet(ActionDescriptor[] actions) + { + var random = new Random(Seed); + + var data = new List>>(); + + for (var i = 0; i < actions.Length; i += 2) + { + var action = actions[i]; + var routeValues = new RouteValueDictionary(action.RouteValues); + var matches = NaiveSelectCandiates(actions, routeValues); + if (matches.Count == 0) + { + throw new InvalidOperationException("This should have at least one match."); + } + + + data.Add(new KeyValuePair>(routeValues, matches)); + } + + for (var i = 1; i < actions.Length; i += 3) + { + var action = actions[i]; + var routeValues = new RouteValueDictionary(action.RouteValues); + + // Make one of the route values not match. + routeValues[routeValues.First().Key] = ((string)routeValues.First().Value) + "fkdkfdkkf"; + + var matches = NaiveSelectCandiates(actions, routeValues); + if (matches.Count != 0) + { + throw new InvalidOperationException("This should have 0 matches."); + } + + data.Add(new KeyValuePair>(routeValues, matches)); + } + + return data.ToArray(); + } + + private static void Verify(IReadOnlyList expected, IReadOnlyList actual) + { + if (expected.Count == 0 && actual == null) + { + return; + } + + if (expected.Count != actual.Count) + { + throw new InvalidOperationException("The count is different."); + } + + for (var i = 0; i < actual.Count; i++) + { + if (!object.ReferenceEquals(expected[i], actual[i])) + { + throw new InvalidOperationException("The actions don't match."); + } + } + } + + private static IActionSelector CreateActionSelector(ActionDescriptor[] actions) + { + var actionCollection = new MockActionDescriptorCollectionProvider(actions); + + return new ActionSelector( + actionCollection, + new ActionConstraintCache(actionCollection, Enumerable.Empty()), + NullLoggerFactory.Instance); + } + + private class MockActionDescriptorCollectionProvider : IActionDescriptorCollectionProvider + { + public MockActionDescriptorCollectionProvider(ActionDescriptor[] actions) + { + ActionDescriptors = new ActionDescriptorCollection(actions, 0); + } + + public ActionDescriptorCollection ActionDescriptors { get; } + } + + private class MockRouter : IRouter + { + public static readonly IRouter Instance = new MockRouter(); + + public VirtualPathData GetVirtualPath(VirtualPathContext context) + { + throw new NotImplementedException(); + } + + public Task RouteAsync(RouteContext context) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/AssemblyInfo.cs b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/AssemblyInfo.cs new file mode 100644 index 0000000000..32248e0d1b --- /dev/null +++ b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/AssemblyInfo.cs @@ -0,0 +1 @@ +[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark] diff --git a/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/Microsoft.AspNetCore.Mvc.Performance.csproj b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/Microsoft.AspNetCore.Mvc.Performance.csproj new file mode 100644 index 0000000000..da89cbef0a --- /dev/null +++ b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/Microsoft.AspNetCore.Mvc.Performance.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp2.1 + Exe + true + true + + + + + + + + + + + + diff --git a/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/readme.md b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/readme.md new file mode 100644 index 0000000000..8adc74351b --- /dev/null +++ b/src/Mvc/benchmarks/Microsoft.AspNetCore.Mvc.Performance/readme.md @@ -0,0 +1,11 @@ +Compile the solution in Release mode (so binaries are available in release) + +To run a specific benchmark add it as parameter +``` +dotnet run -c Release +``` +To run all use `All` as parameter +``` +dotnet run -c Release All +``` +Using no parameter will list all available benchmarks \ No newline at end of file diff --git a/src/Mvc/build/Key.snk b/src/Mvc/build/Key.snk new file mode 100644 index 0000000000..e10e4889c1 Binary files /dev/null and b/src/Mvc/build/Key.snk differ diff --git a/src/Mvc/build/buildpipeline/linux.groovy b/src/Mvc/build/buildpipeline/linux.groovy new file mode 100644 index 0000000000..903f218bb8 --- /dev/null +++ b/src/Mvc/build/buildpipeline/linux.groovy @@ -0,0 +1,10 @@ +@Library('dotnet-ci') _ + +simpleNode('Ubuntu16.04', 'latest-or-auto-docker') { + stage ('Checking out source') { + checkout scm + } + stage ('Build') { + sh './build.sh --ci' + } +} diff --git a/src/Mvc/build/buildpipeline/osx.groovy b/src/Mvc/build/buildpipeline/osx.groovy new file mode 100644 index 0000000000..aaac63686b --- /dev/null +++ b/src/Mvc/build/buildpipeline/osx.groovy @@ -0,0 +1,10 @@ +@Library('dotnet-ci') _ + +simpleNode('OSX10.12','latest') { + stage ('Checking out source') { + checkout scm + } + stage ('Build') { + sh './build.sh --ci' + } +} diff --git a/src/Mvc/build/buildpipeline/pipeline.groovy b/src/Mvc/build/buildpipeline/pipeline.groovy new file mode 100644 index 0000000000..e915cadae1 --- /dev/null +++ b/src/Mvc/build/buildpipeline/pipeline.groovy @@ -0,0 +1,18 @@ +import org.dotnet.ci.pipelines.Pipeline + +def windowsPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/windows.groovy') +def linuxPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/linux.groovy') +def osxPipeline = Pipeline.createPipeline(this, 'build/buildpipeline/osx.groovy') +String configuration = 'Release' +def parameters = [ + 'Configuration': configuration +] + +windowsPipeline.triggerPipelineOnEveryGithubPR("Windows ${configuration} x64 Build", parameters) +windowsPipeline.triggerPipelineOnGithubPush(parameters) + +linuxPipeline.triggerPipelineOnEveryGithubPR("Ubuntu 16.04 ${configuration} Build", parameters) +linuxPipeline.triggerPipelineOnGithubPush(parameters) + +osxPipeline.triggerPipelineOnEveryGithubPR("OSX 10.12 ${configuration} Build", parameters) +osxPipeline.triggerPipelineOnGithubPush(parameters) diff --git a/src/Mvc/build/buildpipeline/windows.groovy b/src/Mvc/build/buildpipeline/windows.groovy new file mode 100644 index 0000000000..8d26f313d4 --- /dev/null +++ b/src/Mvc/build/buildpipeline/windows.groovy @@ -0,0 +1,12 @@ +@Library('dotnet-ci') _ + +// 'node' indicates to Jenkins that the enclosed block runs on a node that matches +// the label 'windows-with-vs' +simpleNode('Windows_NT','latest') { + stage ('Checking out source') { + checkout scm + } + stage ('Build') { + bat '.\\run.cmd -CI default-build' + } +} diff --git a/src/Mvc/build/dependencies.props b/src/Mvc/build/dependencies.props new file mode 100644 index 0000000000..3e21512352 --- /dev/null +++ b/src/Mvc/build/dependencies.props @@ -0,0 +1,103 @@ + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + 0.9.9 + 0.10.13 + 2.1.3-rtm-15802 + 5.2.6 + 2.8.0 + 2.8.0 + 1.7.0 + 2.1.0 + 2.0.0 + 2.1.2 + 2.1.1 + 15.6.1 + 4.7.49 + 2.0.3 + 1.0.1 + 4.5.0 + 4.5.0 + 4.5.1 + 0.8.0 + 2.3.1 + 2.4.0-beta.1.build3945 + + + + + + + + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.2 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.0 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.0 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + 2.1.1 + + diff --git a/src/Mvc/build/repo.props b/src/Mvc/build/repo.props new file mode 100644 index 0000000000..53e1be33f0 --- /dev/null +++ b/src/Mvc/build/repo.props @@ -0,0 +1,23 @@ + + + + + true + + + + + + + + + + Internal.AspNetCore.Universe.Lineup + 2.1.0-rc1-* + https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json + + + + + + diff --git a/src/Mvc/build/sources.props b/src/Mvc/build/sources.props new file mode 100644 index 0000000000..9215df9751 --- /dev/null +++ b/src/Mvc/build/sources.props @@ -0,0 +1,17 @@ + + + + + $(DotNetRestoreSources) + + $(RestoreSources); + https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; + https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; + + + $(RestoreSources); + https://api.nuget.org/v3/index.json; + + + diff --git a/src/Mvc/samples/MvcSandbox/.bowerrc b/src/Mvc/samples/MvcSandbox/.bowerrc new file mode 100644 index 0000000000..6406626abf --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "wwwroot/lib" +} diff --git a/src/Mvc/samples/MvcSandbox/.gitignore b/src/Mvc/samples/MvcSandbox/.gitignore new file mode 100644 index 0000000000..ea32980d43 --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/.gitignore @@ -0,0 +1,2 @@ +# Ignore everything +* diff --git a/src/Mvc/samples/MvcSandbox/Controllers/HomeController.cs b/src/Mvc/samples/MvcSandbox/Controllers/HomeController.cs new file mode 100644 index 0000000000..2aa4ff6829 --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Controllers/HomeController.cs @@ -0,0 +1,18 @@ +// 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 Microsoft.AspNetCore.Mvc; + +namespace MvcSandbox.Controllers +{ + public class HomeController : Controller + { + [ModelBinder] + public string Id { get; set; } + + public IActionResult Index() + { + return View(); + } + } +} diff --git a/src/Mvc/samples/MvcSandbox/Models/Index.cs b/src/Mvc/samples/MvcSandbox/Models/Index.cs new file mode 100644 index 0000000000..5f282702bb --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Models/Index.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Mvc/samples/MvcSandbox/Models/TestModel.cs b/src/Mvc/samples/MvcSandbox/Models/TestModel.cs new file mode 100644 index 0000000000..29e881e9a4 --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Models/TestModel.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. + +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace MvcSandbox +{ + public class TestModel : PageModel + { + public string Name { get; private set; } = "World"; + + public IActionResult OnPost(string name) + { + Name = name; + return Page(); + } + } +} diff --git a/src/Mvc/samples/MvcSandbox/MvcSandbox.csproj b/src/Mvc/samples/MvcSandbox/MvcSandbox.csproj new file mode 100644 index 0000000000..116e4a2f66 --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/MvcSandbox.csproj @@ -0,0 +1,27 @@ + + + + netcoreapp2.1 + $(TargetFrameworks);net461 + + + + true + + + + + + + + + + + + + + + + + + diff --git a/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml b/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml new file mode 100644 index 0000000000..3c565a3b59 --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml @@ -0,0 +1,31 @@ +@page +@model TestModel +@{ + + ViewData["Title"] = "Hello from pages"; +} + +@functions { + + [TempData] + public string Message { get; set; } +} + + + + RazorPages says Hello @Model.Name! + + This file should give you a quick view of a Mvc Razor Page in action. + + Message from TempData: @Message + @{ + Message = $"You visited this page at {DateTime.Now}."; + } + + + + Say hello to + + + + diff --git a/src/Mvc/samples/MvcSandbox/Pages/_ViewImports.cshtml b/src/Mvc/samples/MvcSandbox/Pages/_ViewImports.cshtml new file mode 100644 index 0000000000..f4b9eaae4f --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Pages/_ViewImports.cshtml @@ -0,0 +1,2 @@ +@namespace MvcSandbox.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/Mvc/samples/MvcSandbox/Pages/_ViewStart.cshtml b/src/Mvc/samples/MvcSandbox/Pages/_ViewStart.cshtml new file mode 100644 index 0000000000..26214bbe6c --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Pages/_ViewStart.cshtml @@ -0,0 +1 @@ +@{ Layout = "_Layout";} \ No newline at end of file diff --git a/src/Mvc/samples/MvcSandbox/Startup.cs b/src/Mvc/samples/MvcSandbox/Startup.cs new file mode 100644 index 0000000000..b963a03a6f --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Startup.cs @@ -0,0 +1,55 @@ +// 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.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace MvcSandbox +{ + public class Startup + { + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app) + { + app.UseDeveloperExceptionPage(); + app.UseStaticFiles(); + app.UseMvc(routes => + { + routes.MapRoute( + name: "default", + template: "{controller=Home}/{action=Index}/{id?}"); + }); + } + + public static void Main(string[] args) + { + var host = CreateWebHostBuilder(args) + .Build(); + + host.Run(); + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + new WebHostBuilder() + .UseContentRoot(Directory.GetCurrentDirectory()) + .ConfigureLogging(factory => + { + factory + .AddConsole() + .AddDebug(); + }) + .UseIISIntegration() + .UseKestrel() + .UseStartup(); + } +} + diff --git a/src/Mvc/samples/MvcSandbox/Views/Home/Index.cshtml b/src/Mvc/samples/MvcSandbox/Views/Home/Index.cshtml new file mode 100644 index 0000000000..93a5e737b0 --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Views/Home/Index.cshtml @@ -0,0 +1,12 @@ +@{ + ViewData["Title"] = "Home Page"; +} + + + + Sandbox + + This sandbox should give you a quick view of a basic MVC application. + + + diff --git a/src/Mvc/samples/MvcSandbox/Views/Shared/_Layout.cshtml b/src/Mvc/samples/MvcSandbox/Views/Shared/_Layout.cshtml new file mode 100644 index 0000000000..2308354c26 --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Views/Shared/_Layout.cshtml @@ -0,0 +1,42 @@ + + + + + + @ViewData["Title"] - MvcSandbox + + + + + + + + Toggle navigation + + + + + MvcSandbox + + + + Home + PagesHome + + + + + + @RenderBody() + + + + + + + + @RenderSection("scripts", required: false) + + diff --git a/src/Mvc/samples/MvcSandbox/Views/_ViewImports.cshtml b/src/Mvc/samples/MvcSandbox/Views/_ViewImports.cshtml new file mode 100644 index 0000000000..96ba4523d1 --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Views/_ViewImports.cshtml @@ -0,0 +1,2 @@ +@using MvcSandbox +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/Mvc/samples/MvcSandbox/Views/_ViewStart.cshtml b/src/Mvc/samples/MvcSandbox/Views/_ViewStart.cshtml new file mode 100644 index 0000000000..a5f10045db --- /dev/null +++ b/src/Mvc/samples/MvcSandbox/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +} diff --git a/src/Mvc/src/Directory.Build.props b/src/Mvc/src/Directory.Build.props new file mode 100644 index 0000000000..4b89a431e7 --- /dev/null +++ b/src/Mvc/src/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptor.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptor.cs new file mode 100644 index 0000000000..a1ced7244b --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptor.cs @@ -0,0 +1,64 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.ActionConstraints; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.Routing; + +namespace Microsoft.AspNetCore.Mvc.Abstractions +{ + public class ActionDescriptor + { + public ActionDescriptor() + { + Id = Guid.NewGuid().ToString(); + Properties = new Dictionary(); + RouteValues = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + /// + /// Gets an id which uniquely identifies the action. + /// + public string Id { get; } + + /// + /// Gets or sets the collection of route values that must be provided by routing + /// for the action to be selected. + /// + public IDictionary RouteValues { get; set; } + + public AttributeRouteInfo AttributeRouteInfo { get; set; } + + /// + /// The set of constraints for this action. Must all be satisfied for the action to be selected. + /// + public IList ActionConstraints { get; set; } + + /// + /// The set of parameters associated with this action. + /// + public IList Parameters { get; set; } + + /// + /// The set of properties which are model bound. + /// + public IList BoundProperties { get; set; } + + /// + /// The set of filters associated with this action. + /// + public IList FilterDescriptors { get; set; } + + /// + /// A friendly name for this action. + /// + public virtual string DisplayName { get; set; } + + /// + /// Stores arbitrary metadata properties associated with the . + /// + public IDictionary Properties { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptorExtensions.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptorExtensions.cs new file mode 100644 index 0000000000..3cd94db1f1 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptorExtensions.cs @@ -0,0 +1,60 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.Abstractions +{ + /// + /// Extension methods for . + /// + public static class ActionDescriptorExtensions + { + /// + /// Gets the value of a property from the collection + /// using the provided value of as the key. + /// + /// The type of the property. + /// The action descriptor. + /// The property or the default value of . + public static T GetProperty(this ActionDescriptor actionDescriptor) + { + if (actionDescriptor == null) + { + throw new ArgumentNullException(nameof(actionDescriptor)); + } + + object value; + if (actionDescriptor.Properties.TryGetValue(typeof(T), out value)) + { + return (T)value; + } + else + { + return default(T); + } + } + + /// + /// Sets the value of an property in the collection using + /// the provided value of as the key. + /// + /// The type of the property. + /// The action descriptor. + /// The value of the property. + public static void SetProperty(this ActionDescriptor actionDescriptor, T value) + { + if (actionDescriptor == null) + { + throw new ArgumentNullException(nameof(actionDescriptor)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + actionDescriptor.Properties[typeof(T)] = value; + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptorProviderContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptorProviderContext.cs new file mode 100644 index 0000000000..63ab7dbf0d --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionDescriptorProviderContext.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.Mvc.Abstractions +{ + public class ActionDescriptorProviderContext + { + public IList Results { get; } = new List(); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionInvokerProviderContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionInvokerProviderContext.cs new file mode 100644 index 0000000000..45fd315732 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ActionInvokerProviderContext.cs @@ -0,0 +1,24 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.Abstractions +{ + public class ActionInvokerProviderContext + { + public ActionInvokerProviderContext(ActionContext actionContext) + { + if (actionContext == null) + { + throw new ArgumentNullException(nameof(actionContext)); + } + + ActionContext = actionContext; + } + + public ActionContext ActionContext { get; } + + public IActionInvoker Result { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionDescriptorProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionDescriptorProvider.cs new file mode 100644 index 0000000000..4b52e9aebc --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionDescriptorProvider.cs @@ -0,0 +1,33 @@ +// 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 Microsoft.AspNetCore.Mvc.Abstractions +{ + public interface IActionDescriptorProvider + { + /// + /// Gets the order value for determining the order of execution of providers. Providers execute in + /// ascending numeric value of the property. + /// + /// + /// + /// Providers are executed in an ordering determined by an ascending sort of the property. + /// A provider with a lower numeric value of will have its + /// called before that of a provider with a higher numeric value of + /// . The method is called in the reverse ordering after + /// all calls to . A provider with a lower numeric value of + /// will have its method called after that of a provider + /// with a higher numeric value of . + /// + /// + /// If two providers have the same numeric value of , then their relative execution order + /// is undefined. + /// + /// + int Order { get; } + + void OnProvidersExecuting(ActionDescriptorProviderContext context); + + void OnProvidersExecuted(ActionDescriptorProviderContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionInvoker.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionInvoker.cs new file mode 100644 index 0000000000..ed3650cc23 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionInvoker.cs @@ -0,0 +1,23 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Abstractions +{ + /// + /// Defines an interface for invoking an MVC action. + /// + /// + /// An is created for each request the MVC handles by querying the set of + /// instances. See for more information. + /// + public interface IActionInvoker + { + /// + /// Invokes an MVC action. + /// + /// A which will complete when action processing has completed. + Task InvokeAsync(); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionInvokerProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionInvokerProvider.cs new file mode 100644 index 0000000000..c324d7b330 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/IActionInvokerProvider.cs @@ -0,0 +1,63 @@ +// 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 Microsoft.AspNetCore.Mvc.Abstractions +{ + /// + /// Defines an interface for components that can create an for the + /// current request. + /// + /// + /// + /// instances form a pipeline that results in the creation of an + /// . The instances are ordered by + /// an ascending sort of the . + /// + /// + /// To create an , each provider has its method + /// called in sequence and given the same instance of . Then each + /// provider has its method called in the reverse order. The result is + /// the value of . + /// + /// + /// As providers are called in a predefined sequence, each provider has a chance to observe and decorate the + /// result of the providers that have already run. + /// + /// + public interface IActionInvokerProvider + { + /// + /// Gets the order value for determining the order of execution of providers. Providers execute in + /// ascending numeric value of the property. + /// + /// + /// + /// Providers are executed in an ordering determined by an ascending sort of the property. + /// A provider with a lower numeric value of will have its + /// called before that of a provider with a higher numeric value of + /// . The method is called in the reverse ordering after + /// all calls to . A provider with a lower numeric value of + /// will have its method called after that of a provider + /// with a higher numeric value of . + /// + /// + /// If two providers have the same numeric value of , then their relative execution order + /// is undefined. + /// + /// + int Order { get; } + + /// + /// Called to execute the provider. + /// + /// The . + void OnProvidersExecuting(ActionInvokerProviderContext context); + + /// + /// Called to execute the provider, after the methods of all providers, + /// have been called. + /// + /// The . + void OnProvidersExecuted(ActionInvokerProviderContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ParameterDescriptor.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ParameterDescriptor.cs new file mode 100644 index 0000000000..890c3e8526 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Abstractions/ParameterDescriptor.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace Microsoft.AspNetCore.Mvc.Abstractions +{ + public class ParameterDescriptor + { + public string Name { get; set; } + + public Type ParameterType { get; set; } + + public BindingInfo BindingInfo { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintContext.cs new file mode 100644 index 0000000000..68ee228d0e --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintContext.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using Microsoft.AspNetCore.Routing; + +namespace Microsoft.AspNetCore.Mvc.ActionConstraints +{ + /// + /// Context for execution. + /// + public class ActionConstraintContext + { + /// + /// The list of . This includes all actions that are valid for the current + /// request, as well as their constraints. + /// + public IReadOnlyList Candidates { get; set; } + + /// + /// The current . + /// + public ActionSelectorCandidate CurrentCandidate { get; set; } + + /// + /// The . + /// + public RouteContext RouteContext { get; set; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintItem.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintItem.cs new file mode 100644 index 0000000000..7022a8f283 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintItem.cs @@ -0,0 +1,43 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ActionConstraints +{ + /// + /// Represents an with or without a corresponding + /// . + /// + public class ActionConstraintItem + { + /// + /// Creates a new . + /// + /// The instance. + public ActionConstraintItem(IActionConstraintMetadata metadata) + { + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + Metadata = metadata; + } + + /// + /// The associated with . + /// + public IActionConstraint Constraint { get; set; } + + /// + /// The instance. + /// + public IActionConstraintMetadata Metadata { get; } + + /// + /// Gets or sets a value indicating whether or not can be reused across requests. + /// + public bool IsReusable { get; set; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintProviderContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintProviderContext.cs new file mode 100644 index 0000000000..d740257203 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionConstraintProviderContext.cs @@ -0,0 +1,62 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Abstractions; + +namespace Microsoft.AspNetCore.Mvc.ActionConstraints +{ + /// + /// Context for an action constraint provider. + /// + public class ActionConstraintProviderContext + { + /// + /// Creates a new . + /// + /// The associated with the request. + /// The for which constraints are being created. + /// The list of objects. + public ActionConstraintProviderContext( + HttpContext context, + ActionDescriptor action, + IList items) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + if (items == null) + { + throw new ArgumentNullException(nameof(items)); + } + + HttpContext = context; + Action = action; + Results = items; + } + + /// + /// The associated with the request. + /// + public HttpContext HttpContext { get; } + + /// + /// The for which constraints are being created. + /// + public ActionDescriptor Action { get; } + + /// + /// The list of objects. + /// + public IList Results { get; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionSelectorCandidate.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionSelectorCandidate.cs new file mode 100644 index 0000000000..c2251cd371 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/ActionSelectorCandidate.cs @@ -0,0 +1,43 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.Abstractions; + +namespace Microsoft.AspNetCore.Mvc.ActionConstraints +{ + /// + /// A candidate action for action selection. + /// + public struct ActionSelectorCandidate + { + /// + /// Creates a new . + /// + /// The representing a candidate for selection. + /// + /// The list of instances associated with . + /// + public ActionSelectorCandidate(ActionDescriptor action, IReadOnlyList constraints) + { + if (action == null) + { + throw new ArgumentNullException(nameof(action)); + } + + Action = action; + Constraints = constraints; + } + + /// + /// The representing a candidate for selection. + /// + public ActionDescriptor Action { get; } + + /// + /// The list of instances associated with . + /// + public IReadOnlyList Constraints { get; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraint.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraint.cs new file mode 100644 index 0000000000..bd59ab6c50 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraint.cs @@ -0,0 +1,55 @@ +// 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 Microsoft.AspNetCore.Mvc.ActionConstraints +{ + /// + /// Supports conditional logic to determine whether or not an associated action is valid to be selected + /// for the given request. + /// + /// + /// Action constraints have the secondary effect of making an action with a constraint applied a better + /// match than one without. + /// + /// Consider two actions, 'A' and 'B' with the same action and controller name. Action 'A' only allows the + /// HTTP POST method (via a constraint) and action 'B' has no constraints. + /// + /// If an incoming request is a POST, then 'A' is considered the best match because it both matches and + /// has a constraint. If an incoming request uses any other verb, 'A' will not be valid for selection + /// due to it's constraint, so 'B' is the best match. + /// + /// + /// Action constraints are also grouped according to their order value. Any constraints with the same + /// group value are considered to be part of the same application policy, and will be executed in the + /// same stage. + /// + /// Stages run in ascending order based on the value of . Given a set of actions which + /// are candidates for selection, the next stage to run is the lowest value of for any + /// constraint of any candidate which is greater than the order of the last stage. + /// + /// Once the stage order is identified, each action has all of its constraints in that stage executed. + /// If any constraint does not match, then that action is not a candidate for selection. If any actions + /// with constraints in the current state are still candidates, then those are the 'best' actions and this + /// process will repeat with the next stage on the set of 'best' actions. If after processing the + /// subsequent stages of the 'best' actions no candidates remain, this process will repeat on the set of + /// 'other' candidate actions from this stage (those without a constraint). + /// + public interface IActionConstraint : IActionConstraintMetadata + { + /// + /// The constraint order. + /// + /// + /// Constraints are grouped into stages by the value of . See remarks on + /// . + /// + int Order { get; } + + /// + /// Determines whether an action is a valid candidate for selection. + /// + /// The . + /// True if the action is valid for selection, otherwise false. + bool Accept(ActionConstraintContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintFactory.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintFactory.cs new file mode 100644 index 0000000000..9c0f597228 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintFactory.cs @@ -0,0 +1,33 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ActionConstraints +{ + /// + /// A factory for . + /// + /// + /// will be invoked during action selection + /// to create constraint instances for an action. + /// + /// Place an attribute implementing this interface on a controller or action to insert an action + /// constraint created by a factory. + /// + public interface IActionConstraintFactory : IActionConstraintMetadata + { + /// + /// Gets a value that indicates if the result of + /// can be reused across requests. + /// + bool IsReusable { get; } + + /// + /// Creates a new . + /// + /// The per-request services. + /// An . + IActionConstraint CreateInstance(IServiceProvider services); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintMetadata.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintMetadata.cs new file mode 100644 index 0000000000..cbfd0970c0 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintMetadata.cs @@ -0,0 +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. + +namespace Microsoft.AspNetCore.Mvc.ActionConstraints +{ + /// + /// A marker interface that identifies a type as metadata for an . + /// + public interface IActionConstraintMetadata + { + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintProvider.cs new file mode 100644 index 0000000000..8c090462ca --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionConstraints/IActionConstraintProvider.cs @@ -0,0 +1,33 @@ +// 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 Microsoft.AspNetCore.Mvc.ActionConstraints +{ + public interface IActionConstraintProvider + { + /// + /// Gets the order value for determining the order of execution of providers. Providers execute in + /// ascending numeric value of the property. + /// + /// + /// + /// Providers are executed in an ordering determined by an ascending sort of the property. + /// A provider with a lower numeric value of will have its + /// called before that of a provider with a higher numeric value of + /// . The method is called in the reverse ordering after + /// all calls to . A provider with a lower numeric value of + /// will have its method called after that of a provider + /// with a higher numeric value of . + /// + /// + /// If two providers have the same numeric value of , then their relative execution order + /// is undefined. + /// + /// + int Order { get; } + + void OnProvidersExecuting(ActionConstraintProviderContext context); + + void OnProvidersExecuted(ActionConstraintProviderContext context); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionContext.cs new file mode 100644 index 0000000000..f7735c1637 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ActionContext.cs @@ -0,0 +1,139 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Routing; + +namespace Microsoft.AspNetCore.Mvc +{ + /// + /// Context object for execution of action which has been selected as part of an HTTP request. + /// + public class ActionContext + { + /// + /// Creates an empty . + /// + /// + /// The default constructor is provided for unit test purposes only. + /// + public ActionContext() + { + ModelState = new ModelStateDictionary(); + } + + /// + /// Creates a new . + /// + /// The to copy. + public ActionContext(ActionContext actionContext) + : this( + actionContext.HttpContext, + actionContext.RouteData, + actionContext.ActionDescriptor, + actionContext.ModelState) + { + if (actionContext == null) + { + throw new ArgumentNullException(nameof(actionContext)); + } + } + + /// + /// Creates a new . + /// + /// The for the current request. + /// The for the current request. + /// The for the selected action. + public ActionContext( + HttpContext httpContext, + RouteData routeData, + ActionDescriptor actionDescriptor) + : this(httpContext, routeData, actionDescriptor, new ModelStateDictionary()) + { + } + + /// + /// Creates a new . + /// + /// The for the current request. + /// The for the current request. + /// The for the selected action. + /// The . + public ActionContext( + HttpContext httpContext, + RouteData routeData, + ActionDescriptor actionDescriptor, + ModelStateDictionary modelState) + { + if (httpContext == null) + { + throw new ArgumentNullException(nameof(httpContext)); + } + + if (routeData == null) + { + throw new ArgumentNullException(nameof(routeData)); + } + + if (actionDescriptor == null) + { + throw new ArgumentNullException(nameof(actionDescriptor)); + } + + if (modelState == null) + { + throw new ArgumentNullException(nameof(modelState)); + } + + HttpContext = httpContext; + RouteData = routeData; + ActionDescriptor = actionDescriptor; + ModelState = modelState; + } + + /// + /// Gets or sets the for the selected action. + /// + /// + /// The property setter is provided for unit test purposes only. + /// + public ActionDescriptor ActionDescriptor + { + get; set; + } + + /// + /// Gets or sets the for the current request. + /// + /// + /// The property setter is provided for unit test purposes only. + /// + public HttpContext HttpContext + { + get; set; + } + + /// + /// Gets the . + /// + public ModelStateDictionary ModelState + { + get; + } + + /// + /// Gets or sets the for the current request. + /// + /// + /// The property setter is provided for unit test purposes only. + /// + public RouteData RouteData + { + get; set; + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiDescription.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiDescription.cs new file mode 100644 index 0000000000..827712f1bc --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiDescription.cs @@ -0,0 +1,63 @@ +// 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.Diagnostics; +using Microsoft.AspNetCore.Mvc.Abstractions; + +namespace Microsoft.AspNetCore.Mvc.ApiExplorer +{ + /// + /// Represents an API exposed by this application. + /// + [DebuggerDisplay("{ActionDescriptor.DisplayName,nq}")] + public class ApiDescription + { + /// + /// Gets or sets for this api. + /// + public ActionDescriptor ActionDescriptor { get; set; } + + /// + /// Gets or sets group name for this api. + /// + public string GroupName { get; set; } + + /// + /// Gets or sets the supported HTTP method for this api, or null if all HTTP methods are supported. + /// + public string HttpMethod { get; set; } + + /// + /// Gets a list of for this api. + /// + public IList ParameterDescriptions { get; } = new List(); + + /// + /// Gets arbitrary metadata properties associated with the . + /// + public IDictionary Properties { get; } = new Dictionary(); + + /// + /// Gets or sets relative url path template (relative to application root) for this api. + /// + public string RelativePath { get; set; } + + /// + /// Gets the list of possible formats for a request. + /// + /// + /// Will be empty if the action does not accept a parameter decorated with the [FromBody] attribute. + /// + public IList SupportedRequestFormats { get; } = new List(); + + /// + /// Gets the list of possible formats for a response. + /// + /// + /// Will be empty if the action returns no response, or if the response type is unclear. Use + /// ProducesAttribute on an action method to specify a response type. + /// + public IList SupportedResponseTypes { get; } = new List(); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiDescriptionProviderContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiDescriptionProviderContext.cs new file mode 100644 index 0000000000..aa9d199089 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiDescriptionProviderContext.cs @@ -0,0 +1,41 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.Abstractions; + +namespace Microsoft.AspNetCore.Mvc.ApiExplorer +{ + /// + /// A context object for providers. + /// + public class ApiDescriptionProviderContext + { + /// + /// Creates a new instance of . + /// + /// The list of actions. + public ApiDescriptionProviderContext(IReadOnlyList actions) + { + if (actions == null) + { + throw new ArgumentNullException(nameof(actions)); + } + + Actions = actions; + + Results = new List(); + } + + /// + /// The list of actions. + /// + public IReadOnlyList Actions { get; } + + /// + /// The list of resulting . + /// + public IList Results { get; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiParameterDescription.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiParameterDescription.cs new file mode 100644 index 0000000000..1f07d2b7ab --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiParameterDescription.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace Microsoft.AspNetCore.Mvc.ApiExplorer +{ + /// + /// A metadata description of an input to an API. + /// + public class ApiParameterDescription + { + /// + /// Gets or sets the . + /// + public ModelMetadata ModelMetadata { get; set; } + + /// + /// Gets or sets the name. + /// + public string Name { get; set; } + + /// + /// Gets or sets the . + /// + public ApiParameterRouteInfo RouteInfo { get; set; } + + /// + /// Gets or sets the . + /// + public BindingSource Source { get; set; } + + /// + /// Gets or sets the parameter type. + /// + public Type Type { get; set; } + + /// + /// Gets or sets the parameter descriptor. + /// + public ParameterDescriptor ParameterDescriptor { get; set; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiParameterRouteInfo.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiParameterRouteInfo.cs new file mode 100644 index 0000000000..6e5cbfc494 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiParameterRouteInfo.cs @@ -0,0 +1,41 @@ +// 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 Microsoft.AspNetCore.Routing; + +namespace Microsoft.AspNetCore.Mvc.ApiExplorer +{ + /// + /// A metadata description of routing information for an . + /// + public class ApiParameterRouteInfo + { + /// + /// Gets or sets the set of objects for the parameter. + /// + /// + /// Route constraints are only applied when a value is bound from a URL's path. See + /// for the data source considered. + /// + public IEnumerable Constraints { get; set; } + + /// + /// Gets or sets the default value for the parameter. + /// + public object DefaultValue { get; set; } + + /// + /// Gets a value indicating whether not a parameter is considered optional by routing. + /// + /// + /// An optional parameter is considered optional by the routing system. This does not imply + /// that the parameter is considered optional by the action. + /// + /// If the parameter uses for the value of + /// then the value may also come from the + /// URL query string or form data. + /// + public bool IsOptional { get; set; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiRequestFormat.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiRequestFormat.cs new file mode 100644 index 0000000000..8d93cc65b3 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiRequestFormat.cs @@ -0,0 +1,23 @@ +// 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 Microsoft.AspNetCore.Mvc.Formatters; + +namespace Microsoft.AspNetCore.Mvc.ApiExplorer +{ + /// + /// A possible format for the body of a request. + /// + public class ApiRequestFormat + { + /// + /// The formatter used to read this request. + /// + public IInputFormatter Formatter { get; set; } + + /// + /// The media type of the request. + /// + public string MediaType { get; set; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiResponseFormat.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiResponseFormat.cs new file mode 100644 index 0000000000..bf04db9da7 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiResponseFormat.cs @@ -0,0 +1,23 @@ +// 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 Microsoft.AspNetCore.Mvc.Formatters; + +namespace Microsoft.AspNetCore.Mvc.ApiExplorer +{ + /// + /// Possible format for an . + /// + public class ApiResponseFormat + { + /// + /// Gets or sets the formatter used to output this response. + /// + public IOutputFormatter Formatter { get; set; } + + /// + /// Gets or sets the media type of the response. + /// + public string MediaType { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiResponseType.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiResponseType.cs new file mode 100644 index 0000000000..6ed9644931 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/ApiResponseType.cs @@ -0,0 +1,53 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace Microsoft.AspNetCore.Mvc.ApiExplorer +{ + /// + /// Possible type of the response body which is formatted by . + /// + public class ApiResponseType + { + /// + /// Gets or sets the response formats supported by this type. + /// + public IList ApiResponseFormats { get; set; } = new List(); + + /// + /// Gets or sets for the or null. + /// + /// + /// Will be null if is null or void. + /// + public ModelMetadata ModelMetadata { get; set; } + + /// + /// Gets or sets the CLR data type of the response or null. + /// + /// + /// Will be null if the action returns no response, or if the response type is unclear. Use + /// Microsoft.AspNetCore.Mvc.ProducesAttribute or Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute on an action method + /// to specify a response type. + /// + public Type Type { get; set; } + + /// + /// Gets or sets the HTTP response status code. + /// + public int StatusCode { get; set; } + + /// + /// Gets or sets a value indicating whether the response type represents a default response. + /// + /// + /// If an has a default response, then the property should be ignored. This response + /// will be used when a more specific response format does not apply. The common use of a default response is to specify the format + /// for communicating error conditions. + /// + public bool IsDefaultResponse { get; set; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/IApiDescriptionProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/IApiDescriptionProvider.cs new file mode 100644 index 0000000000..3f3ab9c595 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ApiExplorer/IApiDescriptionProvider.cs @@ -0,0 +1,41 @@ +// 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 Microsoft.AspNetCore.Mvc.ApiExplorer +{ + public interface IApiDescriptionProvider + { + /// + /// Gets the order value for determining the order of execution of providers. Providers execute in + /// ascending numeric value of the property. + /// + /// + /// + /// Providers are executed in an ordering determined by an ascending sort of the property. + /// A provider with a lower numeric value of will have its + /// called before that of a provider with a higher numeric value of + /// . The method is called in the reverse ordering after + /// all calls to . A provider with a lower numeric value of + /// will have its method called after that of a provider + /// with a higher numeric value of . + /// + /// + /// If two providers have the same numeric value of , then their relative execution order + /// is undefined. + /// + /// + int Order { get; } + + /// + /// Creates or modifies s. + /// + /// The . + void OnProvidersExecuting(ApiDescriptionProviderContext context); + + /// + /// Called after implementations with higher values have been called. + /// + /// The . + void OnProvidersExecuted(ApiDescriptionProviderContext context); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Authorization/IAllowAnonymousFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Authorization/IAllowAnonymousFilter.cs new file mode 100644 index 0000000000..a015f05967 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Authorization/IAllowAnonymousFilter.cs @@ -0,0 +1,14 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters; + +namespace Microsoft.AspNetCore.Mvc.Authorization +{ + /// + /// A filter that allows anonymous requests, disabling some s. + /// + public interface IAllowAnonymousFilter : IFilterMetadata + { + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutedContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutedContext.cs new file mode 100644 index 0000000000..68e0343f04 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutedContext.cs @@ -0,0 +1,96 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Runtime.ExceptionServices; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for action filters, specifically calls. + /// + public class ActionExecutedContext : FilterContext + { + private Exception _exception; + private ExceptionDispatchInfo _exceptionDispatchInfo; + + /// + /// Instantiates a new instance. + /// + /// The . + /// All applicable implementations. + /// The controller instance containing the action. + public ActionExecutedContext( + ActionContext actionContext, + IList filters, + object controller) + : base(actionContext, filters) + { + Controller = controller; + } + + /// + /// Gets or sets an indication that an action filter short-circuited the action and the action filter pipeline. + /// + public virtual bool Canceled { get; set; } + + /// + /// Gets the controller instance containing the action. + /// + public virtual object Controller { get; } + + /// + /// Gets or sets the caught while executing the action or action filters, if + /// any. + /// + public virtual Exception Exception + { + get + { + if (_exception == null && _exceptionDispatchInfo != null) + { + return _exceptionDispatchInfo.SourceException; + } + else + { + return _exception; + } + } + + set + { + _exceptionDispatchInfo = null; + _exception = value; + } + } + + /// + /// Gets or sets the for the + /// , if an was caught and this information captured. + /// + public virtual ExceptionDispatchInfo ExceptionDispatchInfo + { + get + { + return _exceptionDispatchInfo; + } + + set + { + _exception = null; + _exceptionDispatchInfo = value; + } + } + + /// + /// Gets or sets an indication that the has been handled. + /// + public virtual bool ExceptionHandled { get; set; } + + /// + /// Gets or sets the . + /// + public virtual IActionResult Result { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutingContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutingContext.cs new file mode 100644 index 0000000000..65ade1e1c5 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutingContext.cs @@ -0,0 +1,56 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for action filters, specifically and + /// calls. + /// + public class ActionExecutingContext : FilterContext + { + /// + /// Instantiates a new instance. + /// + /// The . + /// All applicable implementations. + /// + /// The arguments to pass when invoking the action. Keys are parameter names. + /// + /// The controller instance containing the action. + public ActionExecutingContext( + ActionContext actionContext, + IList filters, + IDictionary actionArguments, + object controller) + : base(actionContext, filters) + { + if (actionArguments == null) + { + throw new ArgumentNullException(nameof(actionArguments)); + } + + ActionArguments = actionArguments; + Controller = controller; + } + + /// + /// Gets or sets the to execute. Setting to a non-null + /// value inside an action filter will short-circuit the action and any remaining action filters. + /// + public virtual IActionResult Result { get; set; } + + /// + /// Gets the arguments to pass when invoking the action. Keys are parameter names. + /// + public virtual IDictionary ActionArguments { get; } + + /// + /// Gets the controller instance containing the action. + /// + public virtual object Controller { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutionDelegate.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutionDelegate.cs new file mode 100644 index 0000000000..0ee53b4493 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ActionExecutionDelegate.cs @@ -0,0 +1,16 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A delegate that asynchronously returns an indicating the action or the next + /// action filter has executed. + /// + /// + /// A that on completion returns an . + /// + public delegate Task ActionExecutionDelegate(); +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/AuthorizationFilterContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/AuthorizationFilterContext.cs new file mode 100644 index 0000000000..a344d55432 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/AuthorizationFilterContext.cs @@ -0,0 +1,32 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for authorization filters i.e. and + /// implementations. + /// + public class AuthorizationFilterContext : FilterContext + { + /// + /// Instantiates a new instance. + /// + /// The . + /// All applicable implementations. + public AuthorizationFilterContext( + ActionContext actionContext, + IList filters) + : base(actionContext, filters) + { + } + + /// + /// Gets or sets the result of the request. Setting to a non-null value inside + /// an authorization filter will short-circuit the remainder of the filter pipeline. + /// + public virtual IActionResult Result { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ExceptionContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ExceptionContext.cs new file mode 100644 index 0000000000..c0920f057b --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ExceptionContext.cs @@ -0,0 +1,81 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Runtime.ExceptionServices; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for exception filters i.e. and + /// implementations. + /// + public class ExceptionContext : FilterContext + { + private Exception _exception; + private ExceptionDispatchInfo _exceptionDispatchInfo; + + /// + /// Instantiates a new instance. + /// + /// The . + /// All applicable implementations. + public ExceptionContext(ActionContext actionContext, IList filters) + : base(actionContext, filters) + { + } + + /// + /// Gets or sets the caught while executing the action. + /// + public virtual Exception Exception + { + get + { + if (_exception == null && _exceptionDispatchInfo != null) + { + return _exceptionDispatchInfo.SourceException; + } + else + { + return _exception; + } + } + + set + { + _exceptionDispatchInfo = null; + _exception = value; + } + } + + /// + /// Gets or sets the for the + /// , if this information was captured. + /// + public virtual ExceptionDispatchInfo ExceptionDispatchInfo + { + get + { + return _exceptionDispatchInfo; + } + + set + { + _exception = null; + _exceptionDispatchInfo = value; + } + } + + /// + /// Gets or sets an indication that the has been handled. + /// + public virtual bool ExceptionHandled { get; set; } + + /// + /// Gets or sets the . + /// + public virtual IActionResult Result { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterContext.cs new file mode 100644 index 0000000000..961e283399 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterContext.cs @@ -0,0 +1,99 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// An abstract context for filters. + /// + public abstract class FilterContext : ActionContext + { + /// + /// Instantiates a new instance. + /// + /// The . + /// All applicable implementations. + public FilterContext( + ActionContext actionContext, + IList filters) + : base(actionContext) + { + if (filters == null) + { + throw new ArgumentNullException(nameof(filters)); + } + + Filters = filters; + } + + /// + /// Gets all applicable implementations. + /// + public virtual IList Filters { get; } + + /// + /// Returns a value indicating whether the provided is the most effective + /// policy (most specific) applied to the action associated with the . + /// + /// The type of the filter policy. + /// The filter policy instance. + /// + /// true if the provided is the most effective policy, otherwise false. + /// + /// + /// + /// The method is used to implement a common convention + /// for filters that define an overriding behavior. When multiple filters may apply to the same + /// cross-cutting concern, define a common interface for the filters () and + /// implement the filters such that all of the implementations call this method to determine if they should + /// take action. + /// + /// + /// For instance, a global filter might be overridden by placing a filter attribute on an action method. + /// The policy applied directly to the action method could be considered more specific. + /// + /// + /// This mechanism for overriding relies on the rules of order and scope that the filter system + /// provides to control ordering of filters. It is up to the implementor of filters to implement this + /// protocol cooperatively. The filter system has no innate notion of overrides, this is a recommended + /// convention. + /// + /// + public bool IsEffectivePolicy(TMetadata policy) where TMetadata : IFilterMetadata + { + if (policy == null) + { + throw new ArgumentNullException(nameof(policy)); + } + + var effective = FindEffectivePolicy(); + return ReferenceEquals(policy, effective); + } + + /// + /// Returns the most effective (most specific) policy of type applied to + /// the action associated with the . + /// + /// The type of the filter policy. + /// The implementation of applied to the action associated with + /// the + /// + public TMetadata FindEffectivePolicy() where TMetadata : IFilterMetadata + { + // The most specific policy is the one closest to the action (nearest the end of the list). + for (var i = Filters.Count - 1; i >= 0; i--) + { + var filter = Filters[i]; + if (filter is TMetadata match) + { + return match; + } + } + + return default(TMetadata); + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterDescriptor.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterDescriptor.cs new file mode 100644 index 0000000000..a84ea30133 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterDescriptor.cs @@ -0,0 +1,70 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// Descriptor for an . + /// + /// + /// describes an with an order and scope. + /// + /// Order and scope control the execution order of filters. Filters with a higher value of Order execute + /// later in the pipeline. + /// + /// When filters have the same Order, the Scope value is used to determine the order of execution. Filters + /// with a higher value of Scope execute later in the pipeline. See Microsoft.AspNetCore.Mvc.FilterScope + /// for commonly used scopes. + /// + /// For implementations, the filter runs only after an exception has occurred, + /// and so the observed order of execution will be opposite that of other filters. + /// + [DebuggerDisplay("Filter = {Filter.ToString(),nq}, Order = {Order}")] + public class FilterDescriptor + { + /// + /// Creates a new . + /// + /// The . + /// The filter scope. + /// + /// If the implements , then the value of + /// will be taken from . Otherwise the value + /// of will default to 0. + /// + public FilterDescriptor(IFilterMetadata filter, int filterScope) + { + if (filter == null) + { + throw new ArgumentNullException(nameof(filter)); + } + + Filter = filter; + Scope = filterScope; + + + if (Filter is IOrderedFilter orderedFilter) + { + Order = orderedFilter.Order; + } + } + + /// + /// The instance. + /// + public IFilterMetadata Filter { get; } + + /// + /// The filter order. + /// + public int Order { get; set; } + + /// + /// The filter scope. + /// + public int Scope { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterItem.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterItem.cs new file mode 100644 index 0000000000..516acd7d24 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterItem.cs @@ -0,0 +1,63 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// Used to associate executable filters with instances + /// as part of . An should + /// inspect and set and + /// as appropriate. + /// + [DebuggerDisplay("FilterItem: {Filter}")] + public class FilterItem + { + /// + /// Creates a new . + /// + /// The . + public FilterItem(FilterDescriptor descriptor) + { + if (descriptor == null) + { + throw new ArgumentNullException(nameof(descriptor)); + } + + Descriptor = descriptor; + } + + /// + /// Creates a new . + /// + /// The . + /// + public FilterItem(FilterDescriptor descriptor, IFilterMetadata filter) + : this(descriptor) + { + if (filter == null) + { + throw new ArgumentNullException(nameof(filter)); + } + + Filter = filter; + } + + /// + /// Gets the containing the filter metadata. + /// + public FilterDescriptor Descriptor { get; } + + /// + /// Gets or sets the executable associated with . + /// + public IFilterMetadata Filter { get; set; } + + /// + /// Gets or sets a value indicating whether or not can be reused across requests. + /// + public bool IsReusable { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterProviderContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterProviderContext.cs new file mode 100644 index 0000000000..057654eaa4 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/FilterProviderContext.cs @@ -0,0 +1,49 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for filter providers i.e. implementations. + /// + public class FilterProviderContext + { + /// + /// Instantiates a new instance. + /// + /// The . + /// + /// The s, initially created from s or a cache entry. + /// + public FilterProviderContext(ActionContext actionContext, IList items) + { + if (actionContext == null) + { + throw new ArgumentNullException(nameof(actionContext)); + } + + if (items == null) + { + throw new ArgumentNullException(nameof(items)); + } + + ActionContext = actionContext; + Results = items; + } + + /// + /// Gets or sets the . + /// + public ActionContext ActionContext { get; set; } + + /// + /// Gets or sets the s, initially created from s or a + /// cache entry. s should set on existing items or + /// add new s to make executable filters available. + /// + public IList Results { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IActionFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IActionFilter.cs new file mode 100644 index 0000000000..cb37ded4c7 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IActionFilter.cs @@ -0,0 +1,23 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that surrounds execution of the action. + /// + public interface IActionFilter : IFilterMetadata + { + /// + /// Called before the action executes, after model binding is complete. + /// + /// The . + void OnActionExecuting(ActionExecutingContext context); + + /// + /// Called after the action executes, before the action result. + /// + /// The . + void OnActionExecuted(ActionExecutedContext context); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAlwaysRunResultFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAlwaysRunResultFilter.cs new file mode 100644 index 0000000000..e119fd8d93 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAlwaysRunResultFilter.cs @@ -0,0 +1,24 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that surrounds execution of all action results. + /// + /// + /// + /// The interface declares an implementation + /// that should run for all action results. . + /// + /// + /// and instances are not executed in cases where + /// an authorization filter or resource filter short-circuits the request to prevent execution of the action. + /// and implementations + /// are also not executed in cases where an exception filter handles an exception by producing an action result. + /// + /// + public interface IAlwaysRunResultFilter : IResultFilter + { + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncActionFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncActionFilter.cs new file mode 100644 index 0000000000..3342e2b1ff --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncActionFilter.cs @@ -0,0 +1,23 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that asynchronously surrounds execution of the action, after model binding is complete. + /// + public interface IAsyncActionFilter : IFilterMetadata + { + /// + /// Called asynchronously before the action, after model binding is complete. + /// + /// The . + /// + /// The . Invoked to execute the next action filter or the action itself. + /// + /// A that on completion indicates the filter has executed. + Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncAlwaysRunResultFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncAlwaysRunResultFilter.cs new file mode 100644 index 0000000000..f3c0c94dd8 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncAlwaysRunResultFilter.cs @@ -0,0 +1,24 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that asynchronously surrounds execution of all action results. + /// + /// + /// + /// The interface declares an implementation + /// that should run for all action results. . + /// + /// + /// and instances are not executed in cases where + /// an authorization filter or resource filter short-circuits the request to prevent execution of the action. + /// and implementations + /// are also not executed in cases where an exception filter handles an exception by producing an action result. + /// + /// + public interface IAsyncAlwaysRunResultFilter : IAsyncResultFilter + { + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncAuthorizationFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncAuthorizationFilter.cs new file mode 100644 index 0000000000..dd1a797e13 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncAuthorizationFilter.cs @@ -0,0 +1,22 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that asynchronously confirms request authorization. + /// + public interface IAsyncAuthorizationFilter : IFilterMetadata + { + /// + /// Called early in the filter pipeline to confirm request is authorized. + /// + /// The . + /// + /// A that on completion indicates the filter has executed. + /// + Task OnAuthorizationAsync(AuthorizationFilterContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncExceptionFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncExceptionFilter.cs new file mode 100644 index 0000000000..ce3343b463 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncExceptionFilter.cs @@ -0,0 +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. + +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that runs asynchronously after an action has thrown an . + /// + public interface IAsyncExceptionFilter : IFilterMetadata + { + /// + /// Called after an action has thrown an . + /// + /// The . + /// A that on completion indicates the filter has executed. + Task OnExceptionAsync(ExceptionContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncResourceFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncResourceFilter.cs new file mode 100644 index 0000000000..6b4eb7ba9e --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncResourceFilter.cs @@ -0,0 +1,29 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that asynchronously surrounds execution of model binding, the action (and filters) and the action + /// result (and filters). + /// + public interface IAsyncResourceFilter : IFilterMetadata + { + /// + /// Called asynchronously before the rest of the pipeline. + /// + /// The . + /// + /// The . Invoked to execute the next resource filter or the remainder + /// of the pipeline. + /// + /// + /// A which will complete when the remainder of the pipeline completes. + /// + Task OnResourceExecutionAsync( + ResourceExecutingContext context, + ResourceExecutionDelegate next); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncResultFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncResultFilter.cs new file mode 100644 index 0000000000..d6583cbc60 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAsyncResultFilter.cs @@ -0,0 +1,39 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that asynchronously surrounds execution of action results successfully returned from an action. + /// + /// + /// + /// and implementations are executed around the action + /// result only when the action method (or action filters) complete successfully. + /// + /// + /// and instances are not executed in cases where + /// an authorization filter or resource filter short-circuits the request to prevent execution of the action. + /// . and implementations + /// are also not executed in cases where an exception filter handles an exception by producing an action result. + /// + /// + /// To create a result filter that surrounds the execution of all action results, implement + /// either the or the interface. + /// + /// + public interface IAsyncResultFilter : IFilterMetadata + { + /// + /// Called asynchronously before the action result. + /// + /// The . + /// + /// The . Invoked to execute the next result filter or the result itself. + /// + /// A that on completion indicates the filter has executed. + Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAuthorizationFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAuthorizationFilter.cs new file mode 100644 index 0000000000..3dbc4159a0 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IAuthorizationFilter.cs @@ -0,0 +1,17 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that confirms request authorization. + /// + public interface IAuthorizationFilter : IFilterMetadata + { + /// + /// Called early in the filter pipeline to confirm request is authorized. + /// + /// The . + void OnAuthorization(AuthorizationFilterContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IExceptionFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IExceptionFilter.cs new file mode 100644 index 0000000000..5908c2aac9 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IExceptionFilter.cs @@ -0,0 +1,17 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that runs after an action has thrown an . + /// + public interface IExceptionFilter : IFilterMetadata + { + /// + /// Called after an action has thrown an . + /// + /// The . + void OnException(ExceptionContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterContainer.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterContainer.cs new file mode 100644 index 0000000000..26199e6dcf --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterContainer.cs @@ -0,0 +1,16 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that requires a reference back to the that created it. + /// + public interface IFilterContainer + { + /// + /// The that created this filter instance. + /// + IFilterMetadata FilterDefinition { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterFactory.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterFactory.cs new file mode 100644 index 0000000000..e0e844a790 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterFactory.cs @@ -0,0 +1,26 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// An interface for filter metadata which can create an instance of an executable filter. + /// + public interface IFilterFactory : IFilterMetadata + { + /// + /// Gets a value that indicates if the result of + /// can be reused across requests. + /// + bool IsReusable { get; } + + /// + /// Creates an instance of the executable filter. + /// + /// The request . + /// An instance of the executable filter. + IFilterMetadata CreateInstance(IServiceProvider serviceProvider); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterMetadata.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterMetadata.cs new file mode 100644 index 0000000000..458bfdc35c --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterMetadata.cs @@ -0,0 +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. + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// Marker interface for filters handled in the MVC request pipeline. + /// + public interface IFilterMetadata + { + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterProvider.cs new file mode 100644 index 0000000000..46f121b4e8 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IFilterProvider.cs @@ -0,0 +1,45 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A provider. Implementations should update + /// to make executable filters available. + /// + public interface IFilterProvider + { + /// + /// Gets the order value for determining the order of execution of providers. Providers execute in + /// ascending numeric value of the property. + /// + /// + /// + /// Providers are executed in an ordering determined by an ascending sort of the property. + /// A provider with a lower numeric value of will have its + /// called before that of a provider with a higher numeric value of + /// . The method is called in the reverse ordering after + /// all calls to . A provider with a lower numeric value of + /// will have its method called after that of a provider + /// with a higher numeric value of . + /// + /// + /// If two providers have the same numeric value of , then their relative execution order + /// is undefined. + /// + /// + int Order { get; } + + /// + /// Called in increasing . + /// + /// The . + void OnProvidersExecuting(FilterProviderContext context); + + /// + /// Called in decreasing , after all s have executed once. + /// + /// The . + void OnProvidersExecuted(FilterProviderContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IOrderedFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IOrderedFilter.cs new file mode 100644 index 0000000000..36876091ce --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IOrderedFilter.cs @@ -0,0 +1,41 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that specifies the relative order it should run. + /// + public interface IOrderedFilter : IFilterMetadata + { + /// + /// Gets the order value for determining the order of execution of filters. Filters execute in + /// ascending numeric value of the property. + /// + /// + /// + /// Filters are executed in an ordering determined by an ascending sort of the property. + /// + /// + /// Asynchronous filters, such as , surround the execution of subsequent + /// filters of the same filter kind. An asynchronous filter with a lower numeric + /// value will have its filter method, such as , + /// executed before that of a filter with a higher value of . + /// + /// + /// Synchronous filters, such as , have a before-method, such as + /// , and an after-method, such as + /// . A synchronous filter with a lower numeric + /// value will have its before-method executed before that of a filter with a higher value of + /// . During the after-stage of the filter, a synchronous filter with a lower + /// numeric value will have its after-method executed after that of a filter with a higher + /// value of . + /// + /// + /// If two filters have the same numeric value of , then their relative execution order + /// is determined by the filter scope. + /// + /// + int Order { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IResourceFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IResourceFilter.cs new file mode 100644 index 0000000000..410a03c939 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IResourceFilter.cs @@ -0,0 +1,24 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that surrounds execution of model binding, the action (and filters) and the action result + /// (and filters). + /// + public interface IResourceFilter : IFilterMetadata + { + /// + /// Executes the resource filter. Called before execution of the remainder of the pipeline. + /// + /// The . + void OnResourceExecuting(ResourceExecutingContext context); + + /// + /// Executes the resource filter. Called after execution of the remainder of the pipeline. + /// + /// The . + void OnResourceExecuted(ResourceExecutedContext context); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IResultFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IResultFilter.cs new file mode 100644 index 0000000000..bb0ba46bbb --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/IResultFilter.cs @@ -0,0 +1,39 @@ +// 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 Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A filter that surrounds execution of action results successfully returned from an action. + /// + /// + /// + /// and implementations are executed around the action + /// result only when the action method (or action filters) complete successfully. + /// + /// + /// and instances are not executed in cases where + /// an authorization filter or resource filter short-circuits the request to prevent execution of the action. + /// . and implementations + /// are also not executed in cases where an exception filter handles an exception by producing an action result. + /// + /// + /// To create a result filter that surrounds the execution of all action results, implement + /// either the or the interface. + /// + /// + public interface IResultFilter : IFilterMetadata + { + /// + /// Called before the action result executes. + /// + /// The . + void OnResultExecuting(ResultExecutingContext context); + + /// + /// Called after the action result executes. + /// + /// The . + void OnResultExecuted(ResultExecutedContext context); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutedContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutedContext.cs new file mode 100644 index 0000000000..6a54d2c410 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutedContext.cs @@ -0,0 +1,120 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Runtime.ExceptionServices; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for resource filters, specifically calls. + /// + public class ResourceExecutedContext : FilterContext + { + private Exception _exception; + private ExceptionDispatchInfo _exceptionDispatchInfo; + + /// + /// Creates a new . + /// + /// The . + /// The list of instances. + public ResourceExecutedContext(ActionContext actionContext, IList filters) + : base(actionContext, filters) + { + } + + /// + /// Gets or sets a value which indicates whether or not execution was canceled by a resource filter. + /// If true, then a resource filter short-circuited execution by setting + /// . + /// + public virtual bool Canceled { get; set; } + + /// + /// Gets or set the current . + /// + /// + /// + /// Setting or to null will treat + /// the exception as handled, and it will not be rethrown by the runtime. + /// + /// + /// Setting to true will also mark the exception as handled. + /// + /// + public virtual Exception Exception + { + get + { + if (_exception == null && _exceptionDispatchInfo != null) + { + return _exceptionDispatchInfo.SourceException; + } + else + { + return _exception; + } + } + + set + { + _exceptionDispatchInfo = null; + _exception = value; + } + } + + /// + /// Gets or set the current . + /// + /// + /// + /// Setting or to null will treat + /// the exception as handled, and it will not be rethrown by the runtime. + /// + /// + /// Setting to true will also mark the exception as handled. + /// + /// + public virtual ExceptionDispatchInfo ExceptionDispatchInfo + { + get + { + return _exceptionDispatchInfo; + } + + set + { + _exception = null; + _exceptionDispatchInfo = value; + } + } + + /// + /// + /// Gets or sets a value indicating whether or not the current has been handled. + /// + /// + /// If false the will be rethrown by the runtime after resource filters + /// have executed. + /// + /// + public virtual bool ExceptionHandled { get; set; } + + /// + /// Gets or sets the result. + /// + /// + /// + /// The may be provided by execution of the action itself or by another + /// filter. + /// + /// + /// The has already been written to the response before being made available + /// to resource filters. + /// + /// + public virtual IActionResult Result { get; set; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutingContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutingContext.cs new file mode 100644 index 0000000000..46378b3760 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutingContext.cs @@ -0,0 +1,50 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for resource filters, specifically and + /// calls. + /// + public class ResourceExecutingContext : FilterContext + { + /// + /// Creates a new . + /// + /// The . + /// The list of instances. + /// The list of instances. + public ResourceExecutingContext( + ActionContext actionContext, + IList filters, + IList valueProviderFactories) + : base(actionContext, filters) + { + if (valueProviderFactories == null) + { + throw new ArgumentNullException(nameof(valueProviderFactories)); + } + + ValueProviderFactories = valueProviderFactories; + } + + /// + /// Gets or sets the result of the action to be executed. + /// + /// + /// Setting to a non-null value inside a resource filter will + /// short-circuit execution of additional resource filters and the action itself. + /// + public virtual IActionResult Result { get; set; } + + /// + /// Gets the list of instances used by model binding. + /// + public IList ValueProviderFactories { get; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutionDelegate.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutionDelegate.cs new file mode 100644 index 0000000000..ef3531d208 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResourceExecutionDelegate.cs @@ -0,0 +1,14 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A delegate that asynchronously returns a indicating model binding, the + /// action, the action's result, result filters, and exception filters have executed. + /// + /// A that on completion returns a . + public delegate Task ResourceExecutionDelegate(); +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutedContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutedContext.cs new file mode 100644 index 0000000000..ae4947d8bf --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutedContext.cs @@ -0,0 +1,107 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Runtime.ExceptionServices; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for result filters, specifically calls. + /// + public class ResultExecutedContext : FilterContext + { + private Exception _exception; + private ExceptionDispatchInfo _exceptionDispatchInfo; + + /// + /// Instantiates a new instance. + /// + /// The . + /// All applicable implementations. + /// + /// The copied from . + /// + /// The controller instance containing the action. + public ResultExecutedContext( + ActionContext actionContext, + IList filters, + IActionResult result, + object controller) + : base(actionContext, filters) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + Result = result; + Controller = controller; + } + + /// + /// Gets or sets an indication that a result filter set to + /// true and short-circuited the filter pipeline. + /// + public virtual bool Canceled { get; set; } + + /// + /// Gets the controller instance containing the action. + /// + public virtual object Controller { get; } + + /// + /// Gets or sets the caught while executing the result or result filters, if + /// any. + /// + public virtual Exception Exception + { + get + { + if (_exception == null && _exceptionDispatchInfo != null) + { + return _exceptionDispatchInfo.SourceException; + } + else + { + return _exception; + } + } + + set + { + _exceptionDispatchInfo = null; + _exception = value; + } + } + + /// + /// Gets or sets the for the + /// , if an was caught and this information captured. + /// + public virtual ExceptionDispatchInfo ExceptionDispatchInfo + { + get + { + return _exceptionDispatchInfo; + } + + set + { + _exception = null; + _exceptionDispatchInfo = value; + } + } + + /// + /// Gets or sets an indication that the has been handled. + /// + public virtual bool ExceptionHandled { get; set; } + + /// + /// Gets the copied from . + /// + public virtual IActionResult Result { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutingContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutingContext.cs new file mode 100644 index 0000000000..cd4e8775ac --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutingContext.cs @@ -0,0 +1,48 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A context for result filters, specifically and + /// calls. + /// + public class ResultExecutingContext : FilterContext + { + /// + /// Instantiates a new instance. + /// + /// The . + /// All applicable implementations. + /// The of the action and action filters. + /// The controller instance containing the action. + public ResultExecutingContext( + ActionContext actionContext, + IList filters, + IActionResult result, + object controller) + : base(actionContext, filters) + { + Result = result; + Controller = controller; + } + + /// + /// Gets the controller instance containing the action. + /// + public virtual object Controller { get; } + + /// + /// Gets or sets the to execute. Setting to a non-null + /// value inside a result filter will short-circuit the result and any remaining result filters. + /// + public virtual IActionResult Result { get; set; } + + /// + /// Gets or sets an indication the result filter pipeline should be short-circuited. + /// + public virtual bool Cancel { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutionDelegate.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutionDelegate.cs new file mode 100644 index 0000000000..d0ecea6914 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Filters/ResultExecutionDelegate.cs @@ -0,0 +1,14 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Filters +{ + /// + /// A delegate that asynchronously returns an indicating the action result or + /// the next result filter has executed. + /// + /// A that on completion returns an . + public delegate Task ResultExecutionDelegate(); +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/FormatterCollection.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/FormatterCollection.cs new file mode 100644 index 0000000000..401febb5cf --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/FormatterCollection.cs @@ -0,0 +1,58 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// Represents a collection of formatters. + /// + /// The type of formatters in the collection. + public class FormatterCollection : Collection + { + /// + /// Initializes a new instance of the class that is empty. + /// + public FormatterCollection() + { + } + + /// + /// Initializes a new instance of the class + /// as a wrapper for the specified list. + /// + /// The list that is wrapped by the new collection. + public FormatterCollection(IList list) + : base(list) + { + } + + /// + /// Removes all formatters of the specified type. + /// + /// The type to remove. + public void RemoveType() where T : TFormatter + { + RemoveType(typeof(T)); + } + + /// + /// Removes all formatters of the specified type. + /// + /// The type to remove. + public void RemoveType(Type formatterType) + { + for (var i = Count - 1; i >= 0; i--) + { + var formatter = this[i]; + if (formatter.GetType() == formatterType) + { + RemoveAt(i); + } + } + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IInputFormatter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IInputFormatter.cs new file mode 100644 index 0000000000..c56633d16a --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IInputFormatter.cs @@ -0,0 +1,31 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// Reads an object from the request body. + /// + public interface IInputFormatter + { + /// + /// Determines whether this can deserialize an object of the + /// 's . + /// + /// The . + /// + /// true if this can deserialize an object of the + /// 's . false otherwise. + /// + bool CanRead(InputFormatterContext context); + + /// + /// Reads an object from the request body. + /// + /// The . + /// A that on completion deserializes the request body. + Task ReadAsync(InputFormatterContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IInputFormatterExceptionPolicy.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IInputFormatterExceptionPolicy.cs new file mode 100644 index 0000000000..c2032c0e05 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IInputFormatterExceptionPolicy.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 Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// A policy which s can implement to indicate if they want the body model binder + /// to handle all exceptions. By default, all default s implement this interface and + /// have a default value of . + /// + public interface IInputFormatterExceptionPolicy + { + /// + /// Gets the flag to indicate if the body model binder should handle all exceptions. If an exception is handled, + /// the body model binder converts the exception into model state errors, else the exception is allowed to propagate. + /// + InputFormatterExceptionPolicy ExceptionPolicy { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IOutputFormatter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IOutputFormatter.cs new file mode 100644 index 0000000000..a266cf2df7 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/IOutputFormatter.cs @@ -0,0 +1,28 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// Writes an object to the output stream. + /// + public interface IOutputFormatter + { + /// + /// Determines whether this can serialize + /// an object of the specified type. + /// + /// The formatter context associated with the call. + /// Returns true if the formatter can write the response; false otherwise. + bool CanWriteResult(OutputFormatterCanWriteContext context); + + /// + /// Writes the object represented by 's Object property. + /// + /// The formatter context associated with the call. + /// A Task that serializes the value to the 's response message. + Task WriteAsync(OutputFormatterWriteContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterContext.cs new file mode 100644 index 0000000000..001a24dd99 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterContext.cs @@ -0,0 +1,143 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// A context object used by an input formatter for deserializing the request body into an object. + /// + public class InputFormatterContext + { + /// + /// Creates a new instance of . + /// + /// + /// The for the current operation. + /// + /// The name of the model. + /// + /// The for recording errors. + /// + /// + /// The of the model to deserialize. + /// + /// + /// A delegate which can create a for the request body. + /// + public InputFormatterContext( + HttpContext httpContext, + string modelName, + ModelStateDictionary modelState, + ModelMetadata metadata, + Func readerFactory) + : this(httpContext, modelName, modelState, metadata, readerFactory, treatEmptyInputAsDefaultValue: false) + { + } + + /// + /// Creates a new instance of . + /// + /// + /// The for the current operation. + /// + /// The name of the model. + /// + /// The for recording errors. + /// + /// + /// The of the model to deserialize. + /// + /// + /// A delegate which can create a for the request body. + /// + /// + /// A value for the property. + /// + public InputFormatterContext( + HttpContext httpContext, + string modelName, + ModelStateDictionary modelState, + ModelMetadata metadata, + Func readerFactory, + bool treatEmptyInputAsDefaultValue) + { + if (httpContext == null) + { + throw new ArgumentNullException(nameof(httpContext)); + } + + if (modelName == null) + { + throw new ArgumentNullException(nameof(modelName)); + } + + if (modelState == null) + { + throw new ArgumentNullException(nameof(modelState)); + } + + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + if (readerFactory == null) + { + throw new ArgumentNullException(nameof(readerFactory)); + } + + HttpContext = httpContext; + ModelName = modelName; + ModelState = modelState; + Metadata = metadata; + ReaderFactory = readerFactory; + TreatEmptyInputAsDefaultValue = treatEmptyInputAsDefaultValue; + ModelType = metadata.ModelType; + } + + /// + /// Gets a flag to indicate whether the input formatter should allow no value to be provided. + /// If , the input formatter should handle empty input by returning + /// . If , the input + /// formatter should handle empty input by returning the default value for the type + /// . + /// + public bool TreatEmptyInputAsDefaultValue { get; } + + /// + /// Gets the associated with the current operation. + /// + public HttpContext HttpContext { get; } + + /// + /// Gets the name of the model. Used as the key or key prefix for errors added to . + /// + public string ModelName { get; } + + /// + /// Gets the associated with the current operation. + /// + public ModelStateDictionary ModelState { get; } + + /// + /// Gets the requested of the request body deserialization. + /// + public ModelMetadata Metadata { get; } + + /// + /// Gets the requested of the request body deserialization. + /// + public Type ModelType { get; } + + /// + /// Gets a delegate which can create a for the request body. + /// + public Func ReaderFactory { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterException.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterException.cs new file mode 100644 index 0000000000..135d71d701 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterException.cs @@ -0,0 +1,27 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// Exception thrown by when the input is not in an expected format. + /// + public class InputFormatterException : Exception + { + public InputFormatterException() + { + } + + public InputFormatterException(string message) + : base(message) + { + } + + public InputFormatterException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterExceptionPolicy.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterExceptionPolicy.cs new file mode 100644 index 0000000000..be64d4d3ac --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterExceptionPolicy.cs @@ -0,0 +1,52 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// Defines the set of policies that determine how the model binding system interprets exceptions + /// thrown by an . Applications should set + /// MvcOptions.InputFormatterExceptionPolicy to configure this setting. + /// + /// + /// + /// An could throw an exception for several reasons, including: + /// + /// malformed input + /// client disconnect or other I/O problem + /// + /// application configuration problems such as + /// + /// + /// + /// + /// The policy associated with treats + /// all such categories of problems as model state errors, and usually will be reported to the client as + /// an HTTP 400. This was the only policy supported by model binding in ASP.NET Core MVC 1.0, 1.1, and 2.0 + /// and is still the default for historical reasons. + /// + /// + /// The policy associated with + /// treats only and its subclasses as model state errors. This means that + /// exceptions that are not related to the content of the HTTP request (such as a disconnect) will be rethrown, + /// which by default would cause an HTTP 500 response, unless there is exception-handling middleware enabled. + /// + /// + public enum InputFormatterExceptionPolicy + { + /// + /// This value indicates that all exceptions thrown by an will be treated + /// as model state errors. + /// + AllExceptions = 0, + + /// + /// This value indicates that only and subclasses will be treated + /// as model state errors. All other exceptions types will be rethrown and can be handled by a higher + /// level exception handler, such as exception-handling middleware. + /// + MalformedInputExceptions = 1, + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterResult.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterResult.cs new file mode 100644 index 0000000000..2304cd5671 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/InputFormatterResult.cs @@ -0,0 +1,127 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// Result of a operation. + /// + public class InputFormatterResult + { + private static readonly InputFormatterResult _failure = new InputFormatterResult(hasError: true); + private static readonly InputFormatterResult _noValue = new InputFormatterResult(hasError: false); + private static readonly Task _failureAsync = Task.FromResult(_failure); + private static readonly Task _noValueAsync = Task.FromResult(_noValue); + + private InputFormatterResult(bool hasError) + { + HasError = hasError; + } + + private InputFormatterResult(object model) + { + Model = model; + IsModelSet = true; + } + + /// + /// Gets an indication whether the operation had an error. + /// + public bool HasError { get; } + + /// + /// Gets an indication whether a value for the property was supplied. + /// + public bool IsModelSet { get; } + + /// + /// Gets the deserialized . + /// + /// + /// null if is true. + /// + public object Model { get; } + + /// + /// Returns an indicating the + /// operation failed. + /// + /// + /// An indicating the + /// operation failed i.e. with true. + /// + public static InputFormatterResult Failure() + { + return _failure; + } + + /// + /// Returns a that on completion provides an indicating + /// the operation failed. + /// + /// + /// A that on completion provides an indicating the + /// operation failed i.e. with true. + /// + public static Task FailureAsync() + { + return _failureAsync; + } + + /// + /// Returns an indicating the + /// operation was successful. + /// + /// The deserialized . + /// + /// An indicating the + /// operation succeeded i.e. with false. + /// + public static InputFormatterResult Success(object model) + { + return new InputFormatterResult(model); + } + + /// + /// Returns a that on completion provides an indicating + /// the operation was successful. + /// + /// The deserialized . + /// + /// A that on completion provides an indicating the + /// operation succeeded i.e. with false. + /// + public static Task SuccessAsync(object model) + { + return Task.FromResult(Success(model)); + } + + /// + /// Returns an indicating the + /// operation produced no value. + /// + /// + /// An indicating the + /// operation produced no value. + /// + public static InputFormatterResult NoValue() + { + return _noValue; + } + + /// + /// Returns a that on completion provides an indicating + /// the operation produced no value. + /// + /// + /// A that on completion provides an indicating the + /// operation produced no value. + /// + public static Task NoValueAsync() + { + return _noValueAsync; + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/OutputFormatterCanWriteContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/OutputFormatterCanWriteContext.cs new file mode 100644 index 0000000000..e42c092624 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/OutputFormatterCanWriteContext.cs @@ -0,0 +1,77 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// A context object for . + /// + public abstract class OutputFormatterCanWriteContext + { + /// + /// + /// This constructor is obsolete and will be removed in a future version. + /// Please use instead. + /// + /// + /// Creates a new . + /// + /// + [Obsolete("This constructor is obsolete and will be removed in a future version. Please use the constructor taking a HttpContext instead.")] + protected OutputFormatterCanWriteContext() + { + } + + /// + /// Creates a new . + /// + /// The for the current request. + protected OutputFormatterCanWriteContext(HttpContext httpContext) + { + if (httpContext == null) + { + throw new ArgumentNullException(nameof(httpContext)); + } + + HttpContext = httpContext; + } + + /// + /// Gets or sets the context associated with the current operation. + /// + public virtual HttpContext HttpContext { get; protected set; } + + /// + /// Gets or sets the content type to write to the response. + /// + /// + /// An can set this value when its + /// method is called, + /// and expect to see the same value provided in + /// + /// + public virtual StringSegment ContentType { get; set; } + + /// + /// Gets or sets a value to indicate whether the content type was specified by server-side code. + /// This allows to + /// implement stricter filtering on content types that, for example, are being considered purely + /// because of an incoming Accept header. + /// + public virtual bool ContentTypeIsServerDefined { get; set; } + + /// + /// Gets or sets the object to write to the response. + /// + public virtual object Object { get; protected set; } + + /// + /// Gets or sets the of the object to write to the response. + /// + public virtual Type ObjectType { get; protected set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/OutputFormatterWriteContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/OutputFormatterWriteContext.cs new file mode 100644 index 0000000000..fadcfc03e5 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Formatters/OutputFormatterWriteContext.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Text; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Mvc.Formatters +{ + /// + /// A context object for . + /// + public class OutputFormatterWriteContext : OutputFormatterCanWriteContext + { + /// + /// Creates a new . + /// + /// The for the current request. + /// The delegate used to create a for writing the response. + /// The of the object to write to the response. + /// The object to write to the response. + public OutputFormatterWriteContext(HttpContext httpContext, Func writerFactory, Type objectType, object @object) + : base(httpContext) + { + if (writerFactory == null) + { + throw new ArgumentNullException(nameof(writerFactory)); + } + + WriterFactory = writerFactory; + ObjectType = objectType; + Object = @object; + } + + /// + /// + /// Gets or sets a delegate used to create a for writing text to the response. + /// + /// + /// Write to directly to write binary data to the response. + /// + /// + /// + /// + /// The created by this delegate will encode text and write to the + /// stream. Call this delegate to create a + /// for writing text output to the response stream. + /// + /// + /// To implement a formatter that writes binary data to the response stream, do not use the + /// delegate, and use instead. + /// + /// + public virtual Func WriterFactory { get; protected set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/IActionResult.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/IActionResult.cs new file mode 100644 index 0000000000..8cfbee8a9c --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/IActionResult.cs @@ -0,0 +1,22 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc +{ + /// + /// Defines a contract that represents the result of an action method. + /// + public interface IActionResult + { + /// + /// Executes the result operation of the action method asynchronously. This method is called by MVC to process + /// the result of an action method. + /// + /// The context in which the result is executed. The context information includes + /// information about the action that was executed and request information. + /// A task that represents the asynchronous execute operation. + Task ExecuteResultAsync(ActionContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/IUrlHelper.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/IUrlHelper.cs new file mode 100644 index 0000000000..fc329aadc4 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/IUrlHelper.cs @@ -0,0 +1,83 @@ +// 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 Microsoft.AspNetCore.Mvc.Routing; + +namespace Microsoft.AspNetCore.Mvc +{ + /// + /// Defines the contract for the helper to build URLs for ASP.NET MVC within an application. + /// + public interface IUrlHelper + { + /// + /// Gets the for the current request. + /// + ActionContext ActionContext { get; } + + /// + /// Generates a URL with an absolute path for an action method, which contains the action + /// name, controller name, route values, protocol to use, host name, and fragment specified by + /// . Generates an absolute URL if and + /// are non-null. + /// + /// The context object for the generated URLs for an action method. + /// The generated URL. + string Action(UrlActionContext actionContext); + + /// + /// Converts a virtual (relative) path to an application absolute path. + /// + /// + /// If the specified content path does not start with the tilde (~) character, + /// this method returns unchanged. + /// + /// The virtual path of the content. + /// The application absolute path. + string Content(string contentPath); + + /// + /// Returns a value that indicates whether the URL is local. A URL is considered local if it does not have a + /// host / authority part and it has an absolute path. URLs using virtual paths ('~/') are also local. + /// + /// The URL. + /// true if the URL is local; otherwise, false. + /// + /// + /// For example, the following URLs are considered local: + /// + /// /Views/Default/Index.html + /// ~/Index.html + /// + /// + /// + /// The following URLs are non-local: + /// + /// ../Index.html + /// http://www.contoso.com/ + /// http://localhost/Index.html + /// + /// + /// + bool IsLocalUrl(string url); + + /// + /// Generates a URL with an absolute path, which contains the route name, route values, protocol to use, host + /// name, and fragment specified by . Generates an absolute URL if + /// and are non-null. + /// + /// The context object for the generated URLs for a route. + /// The generated URL. + string RouteUrl(UrlRouteContext routeContext); + + /// + /// Generates an absolute URL for the specified and route + /// , which contains the protocol (such as "http" or "https") and host name from the + /// current request. + /// + /// The name of the route that is used to generate URL. + /// An object that contains route values. + /// The generated absolute URL. + string Link(string routeName, object values); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Microsoft.AspNetCore.Mvc.Abstractions.csproj b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Microsoft.AspNetCore.Mvc.Abstractions.csproj new file mode 100644 index 0000000000..4ebbaeec61 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Microsoft.AspNetCore.Mvc.Abstractions.csproj @@ -0,0 +1,22 @@ + + + + ASP.NET Core MVC abstractions and interfaces for action invocation and dispatching, authorization, action filters, formatters, model binding, routing, validation, and more. +Commonly used types: +Microsoft.AspNetCore.Mvc.IActionResult + netstandard2.0 + $(NoWarn);CS1591 + true + aspnetcore;aspnetcoremvc + + + + + + + + + + + + diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/BindingInfo.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/BindingInfo.cs new file mode 100644 index 0000000000..baef377507 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/BindingInfo.cs @@ -0,0 +1,249 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Binding info which represents metadata associated to an action parameter. + /// + public class BindingInfo + { + /// + /// Creates a new . + /// + public BindingInfo() + { + } + + /// + /// Creates a copy of a . + /// + /// The to copy. + public BindingInfo(BindingInfo other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + BindingSource = other.BindingSource; + BinderModelName = other.BinderModelName; + BinderType = other.BinderType; + PropertyFilterProvider = other.PropertyFilterProvider; + RequestPredicate = other.RequestPredicate; + } + + /// + /// Gets or sets the . + /// + public BindingSource BindingSource { get; set; } + + /// + /// Gets or sets the binder model name. + /// + public string BinderModelName { get; set; } + + /// + /// Gets or sets the of the model binder used to bind the model. + /// + public Type BinderType { get; set; } + + /// + /// Gets or sets the . + /// + public IPropertyFilterProvider PropertyFilterProvider { get; set; } + + /// + /// Gets or sets a predicate which determines whether or not the model should be bound based on state + /// from the current request. + /// + public Func RequestPredicate { get; set; } + + /// + /// Constructs a new instance of from the given . + /// + /// This overload does not account for specified via . Consider using + /// overload, or + /// on the result of this method to get a more accurate instance. + /// + /// + /// A collection of attributes which are used to construct + /// + /// A new instance of . + public static BindingInfo GetBindingInfo(IEnumerable attributes) + { + var bindingInfo = new BindingInfo(); + var isBindingInfoPresent = false; + + // BinderModelName + foreach (var binderModelNameAttribute in attributes.OfType()) + { + isBindingInfoPresent = true; + if (binderModelNameAttribute?.Name != null) + { + bindingInfo.BinderModelName = binderModelNameAttribute.Name; + break; + } + } + + // BinderType + foreach (var binderTypeAttribute in attributes.OfType()) + { + isBindingInfoPresent = true; + if (binderTypeAttribute.BinderType != null) + { + bindingInfo.BinderType = binderTypeAttribute.BinderType; + break; + } + } + + // BindingSource + foreach (var bindingSourceAttribute in attributes.OfType()) + { + isBindingInfoPresent = true; + if (bindingSourceAttribute.BindingSource != null) + { + bindingInfo.BindingSource = bindingSourceAttribute.BindingSource; + break; + } + } + + // PropertyFilterProvider + var propertyFilterProviders = attributes.OfType().ToArray(); + if (propertyFilterProviders.Length == 1) + { + isBindingInfoPresent = true; + bindingInfo.PropertyFilterProvider = propertyFilterProviders[0]; + } + else if (propertyFilterProviders.Length > 1) + { + isBindingInfoPresent = true; + bindingInfo.PropertyFilterProvider = new CompositePropertyFilterProvider(propertyFilterProviders); + } + + // RequestPredicate + foreach (var requestPredicateProvider in attributes.OfType()) + { + isBindingInfoPresent = true; + if (requestPredicateProvider.RequestPredicate != null) + { + bindingInfo.RequestPredicate = requestPredicateProvider.RequestPredicate; + break; + } + } + + return isBindingInfoPresent ? bindingInfo : null; + } + + /// + /// Constructs a new instance of from the given and . + /// + /// A collection of attributes which are used to construct . + /// The . + /// A new instance of if any binding metadata was discovered; otherwise or . + public static BindingInfo GetBindingInfo(IEnumerable attributes, ModelMetadata modelMetadata) + { + if (attributes == null) + { + throw new ArgumentNullException(nameof(attributes)); + } + + if (modelMetadata == null) + { + throw new ArgumentNullException(nameof(modelMetadata)); + } + + var bindingInfo = GetBindingInfo(attributes); + var isBindingInfoPresent = bindingInfo != null; + + if (bindingInfo == null) + { + bindingInfo = new BindingInfo(); + } + + isBindingInfoPresent |= bindingInfo.TryApplyBindingInfo(modelMetadata); + + return isBindingInfoPresent ? bindingInfo : null; + } + + /// + /// Applies binding metadata from the specified . + /// + /// Uses values from if no value is already available. + /// + /// + /// The . + /// if any binding metadata from was applied; + /// otherwise. + public bool TryApplyBindingInfo(ModelMetadata modelMetadata) + { + if (modelMetadata == null) + { + throw new ArgumentNullException(nameof(modelMetadata)); + } + + var isBindingInfoPresent = false; + if (BinderModelName == null && modelMetadata.BinderModelName != null) + { + isBindingInfoPresent = true; + BinderModelName = modelMetadata.BinderModelName; + } + + if (BinderType == null && modelMetadata.BinderType != null) + { + isBindingInfoPresent = true; + BinderType = modelMetadata.BinderType; + } + + if (BindingSource == null && modelMetadata.BindingSource != null) + { + isBindingInfoPresent = true; + BindingSource = modelMetadata.BindingSource; + } + + if (PropertyFilterProvider == null && modelMetadata.PropertyFilterProvider != null) + { + isBindingInfoPresent = true; + PropertyFilterProvider = modelMetadata.PropertyFilterProvider; + } + + return isBindingInfoPresent; + } + + private class CompositePropertyFilterProvider : IPropertyFilterProvider + { + private readonly IEnumerable _providers; + + public CompositePropertyFilterProvider(IEnumerable providers) + { + _providers = providers; + } + + public Func PropertyFilter => CreatePropertyFilter(); + + private Func CreatePropertyFilter() + { + var propertyFilters = _providers + .Select(p => p.PropertyFilter) + .Where(p => p != null); + + return (m) => + { + foreach (var propertyFilter in propertyFilters) + { + if (!propertyFilter(m)) + { + return false; + } + } + + return true; + }; + } + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/BindingSource.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/BindingSource.cs new file mode 100644 index 0000000000..995ba57c4d --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/BindingSource.cs @@ -0,0 +1,237 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Abstractions; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A metadata object representing a source of data for model binding. + /// + [DebuggerDisplay("Source: {DisplayName}")] + public class BindingSource : IEquatable + { + /// + /// A for the request body. + /// + public static readonly BindingSource Body = new BindingSource( + "Body", + Resources.BindingSource_Body, + isGreedy: true, + isFromRequest: true); + + /// + /// A for a custom model binder (unknown data source). + /// + public static readonly BindingSource Custom = new BindingSource( + "Custom", + Resources.BindingSource_Custom, + isGreedy: true, + isFromRequest: true); + + /// + /// A for the request form-data. + /// + public static readonly BindingSource Form = new BindingSource( + "Form", + Resources.BindingSource_Form, + isGreedy: false, + isFromRequest: true); + + /// + /// A for the request headers. + /// + public static readonly BindingSource Header = new BindingSource( + "Header", + Resources.BindingSource_Header, + isGreedy: true, + isFromRequest: true); + + /// + /// A for model binding. Includes form-data, query-string + /// and route data from the request. + /// + public static readonly BindingSource ModelBinding = new BindingSource( + "ModelBinding", + Resources.BindingSource_ModelBinding, + isGreedy: false, + isFromRequest: true); + + /// + /// A for the request url path. + /// + public static readonly BindingSource Path = new BindingSource( + "Path", + Resources.BindingSource_Path, + isGreedy: false, + isFromRequest: true); + + /// + /// A for the request query-string. + /// + public static readonly BindingSource Query = new BindingSource( + "Query", + Resources.BindingSource_Query, + isGreedy: false, + isFromRequest: true); + + /// + /// A for request services. + /// + public static readonly BindingSource Services = new BindingSource( + "Services", + Resources.BindingSource_Services, + isGreedy: true, + isFromRequest: false); + + /// + /// A for special parameter types that are not user input. + /// + public static readonly BindingSource Special = new BindingSource( + "Special", + Resources.BindingSource_Special, + isGreedy: true, + isFromRequest: false); + + /// + /// A for , , and . + /// + public static readonly BindingSource FormFile = new BindingSource( + "FormFile", + Resources.BindingSource_FormFile, + isGreedy: true, + isFromRequest: true); + + /// + /// Creates a new . + /// + /// The id, a unique identifier. + /// The display name. + /// A value indicating whether or not the source is greedy. + /// + /// A value indicating whether or not the data comes from the HTTP request. + /// + public BindingSource(string id, string displayName, bool isGreedy, bool isFromRequest) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + Id = id; + DisplayName = displayName; + IsGreedy = isGreedy; + IsFromRequest = isFromRequest; + } + + /// + /// Gets the display name for the source. + /// + public string DisplayName { get; } + + /// + /// Gets the unique identifier for the source. Sources are compared based on their Id. + /// + public string Id { get; } + + /// + /// Gets a value indicating whether or not a source is greedy. A greedy source will bind a model in + /// a single operation, and will not decompose the model into sub-properties. + /// + /// + /// + /// For sources based on a , setting to false + /// will most closely describe the behavior. This value is used inside the default model binders to + /// determine whether or not to attempt to bind properties of a model. + /// + /// + /// Set to true for most custom implementations. + /// + /// + /// If a source represents an which will recursively traverse a model's properties + /// and bind them individually using , then set to + /// true. + /// + /// + public bool IsGreedy { get; } + + /// + /// Gets a value indicating whether or not the binding source uses input from the current HTTP request. + /// + /// + /// Some sources (like ) are based on application state and not user + /// input. These are excluded by default from ApiExplorer diagnostics. + /// + public bool IsFromRequest { get; } + + /// + /// Gets a value indicating whether or not the can accept + /// data from . + /// + /// The to consider as input. + /// True if the source is compatible, otherwise false. + /// + /// When using this method, it is expected that the left-hand-side is metadata specified + /// on a property or parameter for model binding, and the right hand side is a source of + /// data used by a model binder or value provider. + /// + /// This distinction is important as the left-hand-side may be a composite, but the right + /// may not. + /// + public virtual bool CanAcceptDataFrom(BindingSource bindingSource) + { + if (bindingSource == null) + { + throw new ArgumentNullException(nameof(bindingSource)); + } + + if (bindingSource is CompositeBindingSource) + { + var message = Resources.FormatBindingSource_CannotBeComposite( + bindingSource.DisplayName, + nameof(CanAcceptDataFrom)); + throw new ArgumentException(message, nameof(bindingSource)); + } + + return this == bindingSource; + } + + /// + public bool Equals(BindingSource other) + { + return string.Equals(other?.Id, Id, StringComparison.Ordinal); + } + + /// + public override bool Equals(object obj) + { + return Equals(obj as BindingSource); + } + + /// + public override int GetHashCode() + { + return Id.GetHashCode(); + } + + /// + public static bool operator ==(BindingSource s1, BindingSource s2) + { + if (object.ReferenceEquals(s1, null)) + { + return object.ReferenceEquals(s2, null); + } + + return s1.Equals(s2); + } + + /// + public static bool operator !=(BindingSource s1, BindingSource s2) + { + return !(s1 == s2); + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/CompositeBindingSource.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/CompositeBindingSource.cs new file mode 100644 index 0000000000..886deb9951 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/CompositeBindingSource.cs @@ -0,0 +1,116 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc.Abstractions; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A which can represent multiple value-provider data sources. + /// + public class CompositeBindingSource : BindingSource + { + /// + /// Creates a new . + /// + /// + /// The set of entries. + /// Must be value-provider sources and user input. + /// + /// The display name for the composite source. + /// A . + public static CompositeBindingSource Create( + IEnumerable bindingSources, + string displayName) + { + if (bindingSources == null) + { + throw new ArgumentNullException(nameof(bindingSources)); + } + + foreach (var bindingSource in bindingSources) + { + if (bindingSource.IsGreedy) + { + var message = Resources.FormatBindingSource_CannotBeGreedy( + bindingSource.DisplayName, + nameof(CompositeBindingSource)); + throw new ArgumentException(message, nameof(bindingSources)); + } + + if (!bindingSource.IsFromRequest) + { + var message = Resources.FormatBindingSource_MustBeFromRequest( + bindingSource.DisplayName, + nameof(CompositeBindingSource)); + throw new ArgumentException(message, nameof(bindingSources)); + } + + if (bindingSource is CompositeBindingSource) + { + var message = Resources.FormatBindingSource_CannotBeComposite( + bindingSource.DisplayName, + nameof(CompositeBindingSource)); + throw new ArgumentException(message, nameof(bindingSources)); + } + } + + var id = string.Join("&", bindingSources.Select(s => s.Id).OrderBy(s => s, StringComparer.Ordinal)); + return new CompositeBindingSource(id, displayName, bindingSources); + } + + private CompositeBindingSource( + string id, + string displayName, + IEnumerable bindingSources) + : base(id, displayName, isGreedy: false, isFromRequest: true) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + if (bindingSources == null) + { + throw new ArgumentNullException(nameof(bindingSources)); + } + + BindingSources = bindingSources; + } + + /// + /// Gets the set of entries. + /// + public IEnumerable BindingSources { get; } + + /// + public override bool CanAcceptDataFrom(BindingSource bindingSource) + { + if (bindingSource == null) + { + throw new ArgumentNullException(nameof(bindingSource)); + } + + if (bindingSource is CompositeBindingSource) + { + var message = Resources.FormatBindingSource_CannotBeComposite( + bindingSource.DisplayName, + nameof(CanAcceptDataFrom)); + throw new ArgumentException(message, nameof(bindingSource)); + } + + foreach (var source in BindingSources) + { + if (source.CanAcceptDataFrom(bindingSource)) + { + return true; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/EnumGroupAndName.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/EnumGroupAndName.cs new file mode 100644 index 0000000000..0ad0117e5d --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/EnumGroupAndName.cs @@ -0,0 +1,70 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// An abstraction used when grouping enum values for . + /// + public struct EnumGroupAndName + { + private readonly Func _name; + + /// + /// Initializes a new instance of the structure. This constructor should + /// not be used in any site where localization is important. + /// + /// The group name. + /// The name. + public EnumGroupAndName(string group, string name) + { + if (group == null) + { + throw new ArgumentNullException(nameof(group)); + } + + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + Group = group; + _name = () => name; + } + + /// + /// Initializes a new instance of the structure. + /// + /// The group name. + /// A which will return the name. + public EnumGroupAndName( + string group, + Func name) + { + if (group == null) + { + throw new ArgumentNullException(nameof(group)); + } + + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + Group = group; + _name = name; + } + + /// + /// Gets the Group name. + /// + public string Group { get; } + + /// + /// Gets the name. + /// + public string Name => _name(); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IBinderTypeProviderMetadata.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IBinderTypeProviderMetadata.cs new file mode 100644 index 0000000000..75740bba00 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IBinderTypeProviderMetadata.cs @@ -0,0 +1,18 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Provides a which implements . + /// + public interface IBinderTypeProviderMetadata : IBindingSourceMetadata + { + /// + /// A which implements either . + /// + Type BinderType { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IBindingSourceMetadata.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IBindingSourceMetadata.cs new file mode 100644 index 0000000000..4a1ed31275 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IBindingSourceMetadata.cs @@ -0,0 +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. + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Metadata which specifies the data source for model binding. + /// + public interface IBindingSourceMetadata + { + /// + /// Gets the . + /// + /// + /// The is metadata which can be used to determine which data + /// sources are valid for model binding of a property or parameter. + /// + BindingSource BindingSource { get; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelBinder.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelBinder.cs new file mode 100644 index 0000000000..67cfb95218 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelBinder.cs @@ -0,0 +1,32 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Defines an interface for model binders. + /// + public interface IModelBinder + { + /// + /// Attempts to bind a model. + /// + /// The . + /// + /// + /// A which will complete when the model binding process completes. + /// + /// + /// If model binding was successful, the should have + /// set to true. + /// + /// + /// A model binder that completes successfully should set to + /// a value returned from . + /// + /// + Task BindModelAsync(ModelBindingContext bindingContext); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelBinderProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelBinderProvider.cs new file mode 100644 index 0000000000..397fa7e637 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelBinderProvider.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 Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Creates instances. Register + /// instances in MvcOptions. + /// + public interface IModelBinderProvider + { + /// + /// Creates a based on . + /// + /// The . + /// An . + IModelBinder GetBinder(ModelBinderProviderContext context); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelMetadataProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelMetadataProvider.cs new file mode 100644 index 0000000000..32d41f717c --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelMetadataProvider.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + public interface IModelMetadataProvider + { + ModelMetadata GetMetadataForType(Type modelType); + + IEnumerable GetMetadataForProperties(Type modelType); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelNameProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelNameProvider.cs new file mode 100644 index 0000000000..321b7af174 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IModelNameProvider.cs @@ -0,0 +1,16 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Represents an entity which can provide model name as metadata. + /// + public interface IModelNameProvider + { + /// + /// Model name. + /// + string Name { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IPropertyFilterProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IPropertyFilterProvider.cs new file mode 100644 index 0000000000..76ddd463cc --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IPropertyFilterProvider.cs @@ -0,0 +1,18 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Provides a predicate which can determines which model properties should be bound by model binding. + /// + public interface IPropertyFilterProvider + { + /// + /// Gets a predicate which can determines which model properties should be bound by model binding. + /// + Func PropertyFilter { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IRequestPredicateProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IRequestPredicateProvider.cs new file mode 100644 index 0000000000..ab72771f22 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IRequestPredicateProvider.cs @@ -0,0 +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. + +using System; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// An interface that allows a top-level model to be bound or not bound based on state associated + /// with the current request. + /// + public interface IRequestPredicateProvider + { + /// + /// Gets a function which determines whether or not the model object should be bound based + /// on the current request. + /// + Func RequestPredicate { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IValueProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IValueProvider.cs new file mode 100644 index 0000000000..4e57509298 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IValueProvider.cs @@ -0,0 +1,25 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Defines the methods that are required for a value provider. + /// + public interface IValueProvider + { + /// + /// Determines whether the collection contains the specified prefix. + /// + /// The prefix to search for. + /// true if the collection contains the specified prefix; otherwise, false. + bool ContainsPrefix(string prefix); + + /// + /// Retrieves a value object using the specified key. + /// + /// The key of the value object to retrieve. + /// The value object for the specified key. If the exact key is not found, null. + ValueProviderResult GetValue(string key); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IValueProviderFactory.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IValueProviderFactory.cs new file mode 100644 index 0000000000..39b2948fe7 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/IValueProviderFactory.cs @@ -0,0 +1,22 @@ +// 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.Threading.Tasks; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A factory for creating instances. + /// + public interface IValueProviderFactory + { + /// + /// Creates a with values from the current request + /// and adds it to list. + /// + /// The . + /// A that when completed will add an instance + /// to list if applicable. + Task CreateValueProviderAsync(ValueProviderFactoryContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelBindingMessageProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelBindingMessageProvider.cs new file mode 100644 index 0000000000..5ab37cfd8b --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelBindingMessageProvider.cs @@ -0,0 +1,95 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata +{ + /// + /// Provider for error messages the model binding system detects. + /// + public abstract class ModelBindingMessageProvider + { + /// + /// Error message the model binding system adds when a property with an associated + /// BindRequiredAttribute is not bound. + /// + /// Default is "A value for the '{0}' property was not provided.". + public virtual Func MissingBindRequiredValueAccessor { get; } + + /// + /// Error message the model binding system adds when either the key or the value of a + /// is bound but not both. + /// + /// Default is "A value is required.". + public virtual Func MissingKeyOrValueAccessor { get; } + + /// + /// Error message the model binding system adds when no value is provided for the request body, + /// but a value is required. + /// + /// Default is "A non-empty request body is required.". + public virtual Func MissingRequestBodyRequiredValueAccessor { get; } + + /// + /// Error message the model binding system adds when a null value is bound to a + /// non- property. + /// + /// Default is "The value '{0}' is invalid.". + public virtual Func ValueMustNotBeNullAccessor { get; } + + /// + /// Error message the model binding system adds when is of type + /// or , value is known, and error is associated + /// with a property. + /// + /// Default is "The value '{0}' is not valid for {1}.". + public virtual Func AttemptedValueIsInvalidAccessor { get; } + + /// + /// Error message the model binding system adds when is of type + /// or , value is known, and error is associated + /// with a collection element or action parameter. + /// + /// Default is "The value '{0}' is not valid.". + public virtual Func NonPropertyAttemptedValueIsInvalidAccessor { get; } + + /// + /// Error message the model binding system adds when is of type + /// or , value is unknown, and error is associated + /// with a property. + /// + /// Default is "The supplied value is invalid for {0}.". + public virtual Func UnknownValueIsInvalidAccessor { get; } + + /// + /// Error message the model binding system adds when is of type + /// or , value is unknown, and error is associated + /// with a collection element or action parameter. + /// + /// Default is "The supplied value is invalid.". + public virtual Func NonPropertyUnknownValueIsInvalidAccessor { get; } + + /// + /// Fallback error message HTML and tag helpers display when a property is invalid but the + /// s have null s. + /// + /// Default is "The value '{0}' is invalid.". + public virtual Func ValueIsInvalidAccessor { get; } + + /// + /// Error message HTML and tag helpers add for client-side validation of numeric formats. Visible in the + /// browser if the field for a float (for example) property does not have a correctly-formatted value. + /// + /// Default is "The field {0} must be a number.". + public virtual Func ValueMustBeANumberAccessor { get; } + + /// + /// Error message HTML and tag helpers add for client-side validation of numeric formats. Visible in the + /// browser if the field for a float (for example) collection element or action parameter does not have a + /// correctly-formatted value. + /// + /// Default is "The field must be a number.". + public virtual Func NonPropertyValueMustBeANumberAccessor { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelMetadataIdentity.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelMetadataIdentity.cs new file mode 100644 index 0000000000..913576e6a8 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelMetadataIdentity.cs @@ -0,0 +1,177 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Reflection; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.Extensions.Internal; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata +{ + /// + /// A key type which identifies a . + /// + public struct ModelMetadataIdentity : IEquatable + { + /// + /// Creates a for the provided model . + /// + /// The model . + /// A . + public static ModelMetadataIdentity ForType(Type modelType) + { + if (modelType == null) + { + throw new ArgumentNullException(nameof(modelType)); + } + + return new ModelMetadataIdentity() + { + ModelType = modelType, + }; + } + + /// + /// Creates a for the provided property. + /// + /// The model type. + /// The name of the property. + /// The container type of the model property. + /// A . + public static ModelMetadataIdentity ForProperty( + Type modelType, + string name, + Type containerType) + { + if (modelType == null) + { + throw new ArgumentNullException(nameof(modelType)); + } + + if (containerType == null) + { + throw new ArgumentNullException(nameof(containerType)); + } + + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(name)); + } + + return new ModelMetadataIdentity() + { + ModelType = modelType, + Name = name, + ContainerType = containerType, + }; + } + + /// + /// Creates a for the provided parameter. + /// + /// The . + /// A . + public static ModelMetadataIdentity ForParameter(ParameterInfo parameter) + => ForParameter(parameter, parameter?.ParameterType); + + /// + /// Creates a for the provided parameter with the specified + /// model type. + /// + /// The . + /// The model type. + /// A . + private static ModelMetadataIdentity ForParameter(ParameterInfo parameter, Type modelType) + { + if (parameter == null) + { + throw new ArgumentNullException(nameof(parameter)); + } + + if (modelType == null) + { + throw new ArgumentNullException(nameof(modelType)); + } + + return new ModelMetadataIdentity() + { + Name = parameter.Name, + ModelType = modelType, + ParameterInfo = parameter, + }; + } + + /// + /// Gets the defining the model property represented by the current + /// instance, or null if the current instance does not represent a property. + /// + public Type ContainerType { get; private set; } + + /// + /// Gets the represented by the current instance. + /// + public Type ModelType { get; private set; } + + /// + /// Gets a value indicating the kind of metadata represented by the current instance. + /// + public ModelMetadataKind MetadataKind + { + get + { + if (ParameterInfo != null) + { + return ModelMetadataKind.Parameter; + } + else if (ContainerType != null && Name != null) + { + return ModelMetadataKind.Property; + } + else + { + return ModelMetadataKind.Type; + } + } + } + + /// + /// Gets the name of the current instance if it represents a parameter or property, or null if + /// the current instance represents a type. + /// + public string Name { get; private set; } + + /// + /// Gets a descriptor for the parameter, or null if this instance + /// does not represent a parameter. + /// + public ParameterInfo ParameterInfo { get; private set; } + + /// + public bool Equals(ModelMetadataIdentity other) + { + return + ContainerType == other.ContainerType && + ModelType == other.ModelType && + Name == other.Name && + ParameterInfo == other.ParameterInfo; + } + + /// + public override bool Equals(object obj) + { + var other = obj as ModelMetadataIdentity?; + return other.HasValue && Equals(other.Value); + } + + /// + public override int GetHashCode() + { + var hash = new HashCodeCombiner(); + hash.Add(ContainerType); + hash.Add(ModelType); + hash.Add(Name, StringComparer.Ordinal); + hash.Add(ParameterInfo); + return hash; + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelMetadataKind.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelMetadataKind.cs new file mode 100644 index 0000000000..4756f85226 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Metadata/ModelMetadataKind.cs @@ -0,0 +1,26 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Metadata +{ + /// + /// Enumeration for the kinds of + /// + public enum ModelMetadataKind + { + /// + /// Used for for a . + /// + Type, + + /// + /// Used for for a property. + /// + Property, + + /// + /// Used for for a parameter. + /// + Parameter, + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBinderProviderContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBinderProviderContext.cs new file mode 100644 index 0000000000..6228923e70 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBinderProviderContext.cs @@ -0,0 +1,53 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A context object for . + /// + public abstract class ModelBinderProviderContext + { + /// + /// Creates an for the given . + /// + /// The for the model. + /// An . + public abstract IModelBinder CreateBinder(ModelMetadata metadata); + + /// + /// Creates an for the given + /// and . + /// + /// The for the model. + /// The that should be used + /// for creating the binder. + /// An . + public virtual IModelBinder CreateBinder(ModelMetadata metadata, BindingInfo bindingInfo) + { + throw new NotSupportedException(); + } + + /// + /// Gets the . + /// + public abstract BindingInfo BindingInfo { get; } + + /// + /// Gets the . + /// + public abstract ModelMetadata Metadata { get; } + + /// + /// Gets the . + /// + public abstract IModelMetadataProvider MetadataProvider { get; } + + /// + /// Gets the . + /// + public virtual IServiceProvider Services { get; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs new file mode 100644 index 0000000000..50c0149cc2 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs @@ -0,0 +1,181 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A context that contains operating information for model binding and validation. + /// + public abstract class ModelBindingContext + { + /// + /// Represents the associated with this context. + /// + /// + /// The property setter is provided for unit testing purposes only. + /// + public abstract ActionContext ActionContext { get; set; } + + /// + /// Gets or sets a model name which is explicitly set using an . + /// + public abstract string BinderModelName { get; set; } + + /// + /// Gets or sets a value which represents the associated with the + /// . + /// + public abstract BindingSource BindingSource { get; set; } + + /// + /// Gets or sets the name of the current field being bound. + /// + public abstract string FieldName { get; set; } + + /// + /// Gets the associated with this context. + /// + public virtual HttpContext HttpContext => ActionContext?.HttpContext; + + /// + /// Gets or sets an indication that the current binder is handling the top-level object. + /// + /// Passed into the model binding system. + public abstract bool IsTopLevelObject { get; set; } + + /// + /// Gets or sets the model value for the current operation. + /// + /// + /// The will typically be set for a binding operation that works + /// against a pre-existing model object to update certain properties. + /// + public abstract object Model { get; set; } + + /// + /// Gets or sets the metadata for the model associated with this context. + /// + public abstract ModelMetadata ModelMetadata { get; set; } + + /// + /// Gets or sets the name of the model. This property is used as a key for looking up values in + /// during model binding. + /// + public abstract string ModelName { get; set; } + + /// + /// Gets or sets the used to capture values + /// for properties in the object graph of the model when binding. + /// + /// + /// The property setter is provided for unit testing purposes only. + /// + public abstract ModelStateDictionary ModelState { get; set; } + + /// + /// Gets the type of the model. + /// + /// + /// The property must be set to access this property. + /// + public virtual Type ModelType => ModelMetadata.ModelType; + + /// + /// Gets or sets a predicate which will be evaluated for each property to determine if the property + /// is eligible for model binding. + /// + public abstract Func PropertyFilter { get; set; } + + /// + /// Gets or sets the . Used for tracking validation state to + /// customize validation behavior for a model object. + /// + /// + /// The property setter is provided for unit testing purposes only. + /// + public abstract ValidationStateDictionary ValidationState { get; set; } + + /// + /// Gets or sets the associated with this context. + /// + public abstract IValueProvider ValueProvider { get; set; } + + /// + /// + /// Gets or sets a which represents the result of the model binding process. + /// + /// + /// Before an is called, will be set to a value indicating + /// failure. The binder should set to a value created with + /// if model binding succeeded. + /// + /// + public abstract ModelBindingResult Result { get; set; } + + /// + /// Pushes a layer of state onto this context. Model binders will call this as part of recursion when binding + /// properties or collection items. + /// + /// + /// to assign to the property. + /// + /// Name to assign to the property. + /// Name to assign to the property. + /// Instance to assign to the property. + /// + /// A scope object which should be used in a using statement where + /// is called. + /// + public abstract NestedScope EnterNestedScope( + ModelMetadata modelMetadata, + string fieldName, + string modelName, + object model); + + /// + /// Pushes a layer of state onto this context. Model binders will call this as part of recursion when binding + /// properties or collection items. + /// + /// + /// A scope object which should be used in a using statement where + /// is called. + /// + public abstract NestedScope EnterNestedScope(); + + /// + /// Removes a layer of state pushed by calling . + /// + protected abstract void ExitNestedScope(); + + /// + /// Return value of . Should be disposed + /// by caller when child binding context state should be popped off of + /// the . + /// + public struct NestedScope : IDisposable + { + private readonly ModelBindingContext _context; + + /// + /// Initializes the for a . + /// + /// + public NestedScope(ModelBindingContext context) + { + _context = context; + } + + /// + /// Exits the created by calling . + /// + public void Dispose() + { + _context.ExitNestedScope(); + } + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingResult.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingResult.cs new file mode 100644 index 0000000000..de57b8bf88 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingResult.cs @@ -0,0 +1,122 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.Internal; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Contains the result of model binding. + /// + public struct ModelBindingResult : IEquatable + { + /// + /// Creates a representing a failed model binding operation. + /// + /// A representing a failed model binding operation. + public static ModelBindingResult Failed() + { + return new ModelBindingResult(model: null, isModelSet: false); + } + + /// + /// Creates a representing a successful model binding operation. + /// + /// The model value. May be null. + /// A representing a successful model bind. + public static ModelBindingResult Success(object model) + { + return new ModelBindingResult( model, isModelSet: true); + } + + private ModelBindingResult(object model, bool isModelSet) + { + Model = model; + IsModelSet = isModelSet; + } + + /// + /// Gets the model associated with this context. + /// + public object Model { get; } + + /// + /// + /// Gets a value indicating whether or not the value has been set. + /// + /// + /// This property can be used to distinguish between a model binder which does not find a value and + /// the case where a model binder sets the null value. + /// + /// + public bool IsModelSet { get; } + + /// + public override bool Equals(object obj) + { + var other = obj as ModelBindingResult?; + if (other == null) + { + return false; + } + else + { + return Equals(other.Value); + } + } + + /// + public override int GetHashCode() + { + var hashCodeCombiner = HashCodeCombiner.Start(); + hashCodeCombiner.Add(IsModelSet); + hashCodeCombiner.Add(Model); + + return hashCodeCombiner.CombinedHash; + } + + /// + public bool Equals(ModelBindingResult other) + { + return + IsModelSet == other.IsModelSet && + object.Equals(Model, other.Model); + } + + /// + public override string ToString() + { + if (IsModelSet) + { + return $"Success '{Model}'"; + } + else + { + return "Failed"; + } + } + + /// + /// Compares objects for equality. + /// + /// A . + /// A . + /// true if the objects are equal, otherwise false. + public static bool operator ==(ModelBindingResult x, ModelBindingResult y) + { + return x.Equals(y); + } + + /// + /// Compares objects for inequality. + /// + /// A . + /// A . + /// true if the objects are not equal, otherwise false. + public static bool operator !=(ModelBindingResult x, ModelBindingResult y) + { + return !x.Equals(y); + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelError.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelError.cs new file mode 100644 index 0000000000..b2125e206d --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelError.cs @@ -0,0 +1,39 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + public class ModelError + { + public ModelError(Exception exception) + : this(exception, errorMessage: null) + { + if (exception == null) + { + throw new ArgumentNullException(nameof(exception)); + } + } + + public ModelError(Exception exception, string errorMessage) + : this(errorMessage) + { + if (exception == null) + { + throw new ArgumentNullException(nameof(exception)); + } + + Exception = exception; + } + + public ModelError(string errorMessage) + { + ErrorMessage = errorMessage ?? string.Empty; + } + + public Exception Exception { get; } + + public string ErrorMessage { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelErrorCollection.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelErrorCollection.cs new file mode 100644 index 0000000000..b8d2e95fb0 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelErrorCollection.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.ObjectModel; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + public class ModelErrorCollection : Collection + { + public void Add(Exception exception) + { + if (exception == null) + { + throw new ArgumentNullException(nameof(exception)); + } + + Add(new ModelError(exception)); + } + + public void Add(string errorMessage) + { + if (errorMessage == null) + { + throw new ArgumentNullException(nameof(errorMessage)); + } + + Add(new ModelError(errorMessage)); + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelMetadata.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelMetadata.cs new file mode 100644 index 0000000000..f78815a7d1 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelMetadata.cs @@ -0,0 +1,510 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Reflection; +using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using Microsoft.Extensions.Internal; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A metadata representation of a model type, property or parameter. + /// + [DebuggerDisplay("{DebuggerToString(),nq}")] + public abstract class ModelMetadata : IEquatable, IModelMetadataProvider + { + /// + /// The default value of . + /// + public static readonly int DefaultOrder = 10000; + + private int? _hashCode; + + /// + /// Creates a new . + /// + /// The . + protected ModelMetadata(ModelMetadataIdentity identity) + { + Identity = identity; + + InitializeTypeInformation(); + } + + /// + /// Gets the type containing the property if this metadata is for a property; otherwise. + /// + public Type ContainerType => Identity.ContainerType; + + /// + /// Gets the metadata for if this metadata is for a property; + /// otherwise. + /// + public virtual ModelMetadata ContainerMetadata + { + get + { + throw new NotImplementedException(); + } + } + + /// + /// Gets a value indicating the kind of metadata element represented by the current instance. + /// + public ModelMetadataKind MetadataKind => Identity.MetadataKind; + + /// + /// Gets the model type represented by the current instance. + /// + public Type ModelType => Identity.ModelType; + + /// + /// Gets the name of the parameter or property if this metadata is for a parameter or property; + /// otherwise i.e. if this is the metadata for a type. + /// + public string Name => Identity.Name; + + /// + /// Gets the name of the parameter if this metadata is for a parameter; otherwise. + /// + public string ParameterName => MetadataKind == ModelMetadataKind.Parameter ? Identity.Name : null; + + /// + /// Gets the name of the property if this metadata is for a property; otherwise. + /// + public string PropertyName => MetadataKind == ModelMetadataKind.Property ? Identity.Name : null; + + /// + /// Gets the key for the current instance. + /// + protected ModelMetadataIdentity Identity { get; } + + /// + /// Gets a collection of additional information about the model. + /// + public abstract IReadOnlyDictionary AdditionalValues { get; } + + /// + /// Gets the collection of instances for the model's properties. + /// + public abstract ModelPropertyCollection Properties { get; } + + /// + /// Gets the name of a model if specified explicitly using . + /// + public abstract string BinderModelName { get; } + + /// + /// Gets the of an of a model if specified explicitly using + /// . + /// + public abstract Type BinderType { get; } + + /// + /// Gets a binder metadata for this model. + /// + public abstract BindingSource BindingSource { get; } + + /// + /// Gets a value indicating whether or not to convert an empty string value or one containing only whitespace + /// characters to null when representing a model as text. + /// + public abstract bool ConvertEmptyStringToNull { get; } + + /// + /// Gets the name of the model's datatype. Overrides in some + /// display scenarios. + /// + /// null unless set manually or through additional metadata e.g. attributes. + public abstract string DataTypeName { get; } + + /// + /// Gets the description of the model. + /// + public abstract string Description { get; } + + /// + /// Gets the format string (see https://msdn.microsoft.com/en-us/library/txafckwd.aspx) used to display the + /// model. + /// + public abstract string DisplayFormatString { get; } + + /// + /// Gets the display name of the model. + /// + public abstract string DisplayName { get; } + + /// + /// Gets the format string (see https://msdn.microsoft.com/en-us/library/txafckwd.aspx) used to edit the model. + /// + public abstract string EditFormatString { get; } + + /// + /// Gets the for elements of if that + /// implements . + /// + /// + /// for T if implements + /// . for object if + /// implements but not . null otherwise i.e. when + /// is false. + /// + public abstract ModelMetadata ElementMetadata { get; } + + /// + /// Gets the ordered and grouped display names and values of all values in + /// . + /// + /// + /// An of of mappings between + /// field groups, names and values. null if is false. + /// + public abstract IEnumerable> EnumGroupedDisplayNamesAndValues { get; } + + /// + /// Gets the names and values of all values in . + /// + /// + /// An of mappings between field names + /// and values. null if is false. + /// + public abstract IReadOnlyDictionary EnumNamesAndValues { get; } + + /// + /// Gets a value indicating whether has a non-null, non-empty + /// value different from the default for the datatype. + /// + public abstract bool HasNonDefaultEditFormat { get; } + + /// + /// Gets a value indicating whether the value should be HTML-encoded. + /// + /// If true, value should be HTML-encoded. Default is true. + public abstract bool HtmlEncode { get; } + + /// + /// Gets a value indicating whether the "HiddenInput" display template should return + /// string.Empty (not the expression value) and whether the "HiddenInput" editor template should not + /// also return the expression value (together with the hidden <input> element). + /// + /// + /// If true, also causes the default display and editor templates to return HTML + /// lacking the usual per-property <div> wrapper around the associated property. Thus the default + /// display template effectively skips the property and the default + /// editor template returns only the hidden <input> element for the property. + /// + public abstract bool HideSurroundingHtml { get; } + + /// + /// Gets a value indicating whether or not the model value can be bound by model binding. This is only + /// applicable when the current instance represents a property. + /// + /// + /// If true then the model value is considered supported by model binding and can be set + /// based on provided input in the request. + /// + public abstract bool IsBindingAllowed { get; } + + /// + /// Gets a value indicating whether or not the model value is required by model binding. This is only + /// applicable when the current instance represents a property. + /// + /// + /// If true then the model value is considered required by model binding and must have a value + /// supplied in the request to be considered valid. + /// + public abstract bool IsBindingRequired { get; } + + /// + /// Gets a value indicating whether is for an . + /// + /// + /// true if type.IsEnum (type.GetTypeInfo().IsEnum for DNX Core 5.0) is true for + /// ; false otherwise. + /// + public abstract bool IsEnum { get; } + + /// + /// Gets a value indicating whether is for an with an + /// associated . + /// + /// + /// true if is true and has an + /// associated ; false otherwise. + /// + public abstract bool IsFlagsEnum { get; } + + /// + /// Gets a value indicating whether or not the model value is read-only. This is only applicable when + /// the current instance represents a property. + /// + public abstract bool IsReadOnly { get; } + + /// + /// Gets a value indicating whether or not the model value is required. This is only applicable when + /// the current instance represents a property. + /// + /// + /// + /// If true then the model value is considered required by validators. + /// + /// + /// By default an implicit System.ComponentModel.DataAnnotations.RequiredAttribute will be added + /// if not present when true.. + /// + /// + public abstract bool IsRequired { get; } + + /// + /// Gets the instance. + /// + public abstract ModelBindingMessageProvider ModelBindingMessageProvider { get; } + + /// + /// Gets a value indicating where the current metadata should be ordered relative to other properties + /// in its containing type. + /// + /// + /// For example this property is used to order items in . + /// The default order is 10000. + /// + /// The order value of the current metadata. + public abstract int Order { get; } + + /// + /// Gets the text to display as a placeholder value for an editor. + /// + public abstract string Placeholder { get; } + + /// + /// Gets the text to display when the model is null. + /// + public abstract string NullDisplayText { get; } + + /// + /// Gets the , which can determine which properties + /// should be model bound. + /// + public abstract IPropertyFilterProvider PropertyFilterProvider { get; } + + /// + /// Gets a value that indicates whether the property should be displayed in read-only views. + /// + public abstract bool ShowForDisplay { get; } + + /// + /// Gets a value that indicates whether the property should be displayed in editable views. + /// + public abstract bool ShowForEdit { get; } + + /// + /// Gets a value which is the name of the property used to display the model. + /// + public abstract string SimpleDisplayProperty { get; } + + /// + /// Gets a string used by the templating system to discover display-templates and editor-templates. + /// + public abstract string TemplateHint { get; } + + /// + /// Gets an implementation that indicates whether this model should be + /// validated. If null, properties with this are validated. + /// + /// Defaults to null. + public virtual IPropertyValidationFilter PropertyValidationFilter => null; + + /// + /// Gets a value that indicates whether properties or elements of the model should be validated. + /// + public abstract bool ValidateChildren { get; } + + /// + /// Gets a collection of metadata items for validators. + /// + public abstract IReadOnlyList ValidatorMetadata { get; } + + /// + /// Gets the for elements of if that + /// implements . + /// + public Type ElementType { get; private set; } + + /// + /// Gets a value indicating whether is a complex type. + /// + /// + /// A complex type is defined as a which has a + /// that can convert from . + /// + public bool IsComplexType { get; private set; } + + /// + /// Gets a value indicating whether or not is a . + /// + public bool IsNullableValueType { get; private set; } + + /// + /// Gets a value indicating whether or not is a collection type. + /// + /// + /// A collection type is defined as a which is assignable to . + /// + public bool IsCollectionType { get; private set; } + + /// + /// Gets a value indicating whether or not is an enumerable type. + /// + /// + /// An enumerable type is defined as a which is assignable to + /// , and is not a . + /// + public bool IsEnumerableType { get; private set; } + + /// + /// Gets a value indicating whether or not allows null values. + /// + public bool IsReferenceOrNullableType { get; private set; } + + /// + /// Gets the underlying type argument if inherits from . + /// Otherwise gets . + /// + /// + /// Identical to unless is true. + /// + public Type UnderlyingOrModelType { get; private set; } + + /// + /// Gets a property getter delegate to get the property value from a model object. + /// + public abstract Func PropertyGetter { get; } + + /// + /// Gets a property setter delegate to set the property value on a model object. + /// + public abstract Action PropertySetter { get; } + + /// + /// Gets a display name for the model. + /// + /// + /// will return the first of the following expressions which has a + /// non- value: , , or ModelType.Name. + /// + /// The display name. + public string GetDisplayName() + { + return DisplayName ?? Name ?? ModelType.Name; + } + + /// + public bool Equals(ModelMetadata other) + { + if (object.ReferenceEquals(this, other)) + { + return true; + } + + if (other == null) + { + return false; + } + else + { + return Identity.Equals(other.Identity); + } + } + + /// + public override bool Equals(object obj) + { + return Equals(obj as ModelMetadata); + } + + /// + public override int GetHashCode() + { + // Normally caching the hashcode would be dangerous, but Identity is deeply immutable so this is safe. + if (_hashCode == null) + { + _hashCode = Identity.GetHashCode(); + } + + return _hashCode.Value; + } + + private void InitializeTypeInformation() + { + Debug.Assert(ModelType != null); + + IsComplexType = !TypeDescriptor.GetConverter(ModelType).CanConvertFrom(typeof(string)); + IsNullableValueType = Nullable.GetUnderlyingType(ModelType) != null; + IsReferenceOrNullableType = !ModelType.GetTypeInfo().IsValueType || IsNullableValueType; + UnderlyingOrModelType = Nullable.GetUnderlyingType(ModelType) ?? ModelType; + + var collectionType = ClosedGenericMatcher.ExtractGenericInterface(ModelType, typeof(ICollection<>)); + IsCollectionType = collectionType != null; + + if (ModelType == typeof(string) || !typeof(IEnumerable).IsAssignableFrom(ModelType)) + { + // Do nothing, not Enumerable. + } + else if (ModelType.IsArray) + { + IsEnumerableType = true; + ElementType = ModelType.GetElementType(); + } + else + { + IsEnumerableType = true; + + var enumerableType = ClosedGenericMatcher.ExtractGenericInterface(ModelType, typeof(IEnumerable<>)); + ElementType = enumerableType?.GenericTypeArguments[0]; + + if (ElementType == null) + { + // ModelType implements IEnumerable but not IEnumerable. + ElementType = typeof(object); + } + + Debug.Assert( + ElementType != null, + $"Unable to find element type for '{ModelType.FullName}' though IsEnumerableType is true."); + } + } + + private string DebuggerToString() + { + switch (MetadataKind) + { + case ModelMetadataKind.Parameter: + return $"ModelMetadata (Parameter: '{ParameterName}' Type: '{ModelType.Name}')"; + case ModelMetadataKind.Property: + return $"ModelMetadata (Property: '{ContainerType.Name}.{PropertyName}' Type: '{ModelType.Name}')"; + case ModelMetadataKind.Type: + return $"ModelMetadata (Type: '{ModelType.Name}')"; + default: + return $"Unsupported MetadataKind '{MetadataKind}'."; + } + } + + /// + public virtual ModelMetadata GetMetadataForType(Type modelType) + { + throw new NotImplementedException(); + } + + /// + public virtual IEnumerable GetMetadataForProperties(Type modelType) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelMetadataProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelMetadataProvider.cs new file mode 100644 index 0000000000..1b4f01cd6d --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelMetadataProvider.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A provider that can supply instances of . + /// + public abstract class ModelMetadataProvider : IModelMetadataProvider + { + /// + /// Supplies metadata describing the properties of a . + /// + /// The . + /// A set of instances describing properties of the . + public abstract IEnumerable GetMetadataForProperties(Type modelType); + + /// + /// Supplies metadata describing a . + /// + /// The . + /// A instance describing the . + public abstract ModelMetadata GetMetadataForType(Type modelType); + + /// + /// Supplies metadata describing a parameter. + /// + /// The . + /// A instance describing the . + public abstract ModelMetadata GetMetadataForParameter(ParameterInfo parameter); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelPropertyCollection.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelPropertyCollection.cs new file mode 100644 index 0000000000..733da709ba --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelPropertyCollection.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A read-only collection of objects which represent model properties. + /// + public class ModelPropertyCollection : ReadOnlyCollection + { + /// + /// Creates a new . + /// + /// The properties. + public ModelPropertyCollection(IEnumerable properties) + : base(properties.ToList()) + { + } + + /// + /// Gets a instance for the property corresponding to . + /// + /// + /// The property name. Property names are compared using . + /// + /// + /// The instance for the property specified by , or + /// null if no match can be found. + /// + public ModelMetadata this[string propertyName] + { + get + { + if (propertyName == null) + { + throw new ArgumentNullException(nameof(propertyName)); + } + + for (var i = 0; i < Items.Count; i++) + { + var property = Items[i]; + if (string.Equals(property.PropertyName, propertyName, StringComparison.Ordinal)) + { + return property; + } + } + + return null; + } + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateDictionary.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateDictionary.cs new file mode 100644 index 0000000000..970e5b6975 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateDictionary.cs @@ -0,0 +1,1249 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Formatters; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Represents the state of an attempt to bind values from an HTTP Request to an action method, which includes + /// validation information. + /// + public class ModelStateDictionary : IReadOnlyDictionary + { + // Make sure to update the doc headers if this value is changed. + /// + /// The default value for of 200. + /// + public static readonly int DefaultMaxAllowedErrors = 200; + + private const char DelimiterDot = '.'; + private const char DelimiterOpen = '['; + + private readonly ModelStateNode _root; + private int _maxAllowedErrors; + + /// + /// Initializes a new instance of the class. + /// + public ModelStateDictionary() + : this(DefaultMaxAllowedErrors) + { + } + + /// + /// Initializes a new instance of the class. + /// + public ModelStateDictionary(int maxAllowedErrors) + { + MaxAllowedErrors = maxAllowedErrors; + var emptySegment = new StringSegment(buffer: string.Empty); + _root = new ModelStateNode(subKey: emptySegment) + { + Key = string.Empty + }; + } + + /// + /// Initializes a new instance of the class by using values that are copied + /// from the specified . + /// + /// The to copy values from. + public ModelStateDictionary(ModelStateDictionary dictionary) + : this(dictionary?.MaxAllowedErrors ?? DefaultMaxAllowedErrors) + { + if (dictionary == null) + { + throw new ArgumentNullException(nameof(dictionary)); + } + + Merge(dictionary); + } + + /// + /// Root entry for the . + /// + public ModelStateEntry Root => _root; + + /// + /// Gets or sets the maximum allowed model state errors in this instance of . + /// Defaults to 200. + /// + /// + /// + /// tracks the number of model errors added by calls to + /// or + /// . + /// Once the value of MaxAllowedErrors - 1 is reached, if another attempt is made to add an error, + /// the error message will be ignored and a will be added. + /// + /// + /// Errors added via modifying directly do not count towards this limit. + /// + /// + public int MaxAllowedErrors + { + get + { + return _maxAllowedErrors; + } + set + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } + + _maxAllowedErrors = value; + } + } + + /// + /// Gets a value indicating whether or not the maximum number of errors have been + /// recorded. + /// + /// + /// Returns true if a has been recorded; + /// otherwise false. + /// + public bool HasReachedMaxErrors => ErrorCount >= MaxAllowedErrors; + + /// + /// Gets the number of errors added to this instance of via + /// or . + /// + public int ErrorCount { get; private set; } + + /// + public int Count { get; private set; } + + /// + /// Gets the key sequence. + /// + public KeyEnumerable Keys => new KeyEnumerable(this); + + /// + IEnumerable IReadOnlyDictionary.Keys => Keys; + + /// + /// Gets the value sequence. + /// + public ValueEnumerable Values => new ValueEnumerable(this); + + /// + IEnumerable IReadOnlyDictionary.Values => Values; + + /// + /// Gets a value that indicates whether any model state values in this model state dictionary is invalid or not validated. + /// + public bool IsValid + { + get + { + return ValidationState == ModelValidationState.Valid || ValidationState == ModelValidationState.Skipped; + } + } + + /// + public ModelValidationState ValidationState => GetValidity(_root) ?? ModelValidationState.Valid; + + /// + public ModelStateEntry this[string key] + { + get + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + TryGetValue(key, out var entry); + return entry; + } + } + + // Flag that indicates if TooManyModelErrorException has already been added to this dictionary. + private bool HasRecordedMaxModelError { get; set; } + + /// + /// Adds the specified to the instance + /// that is associated with the specified . If the maximum number of allowed + /// errors has already been recorded, ensures that a exception is + /// recorded instead. + /// + /// + /// This method allows adding the to the current + /// when is not available or the exact + /// must be maintained for later use (even if it is for example a ). + /// Where is available, use instead. + /// + /// The key of the to add errors to. + /// The to add. + /// + /// True if the given error was added, false if the error was ignored. + /// See . + /// + public bool TryAddModelException(string key, Exception exception) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (exception == null) + { + throw new ArgumentNullException(nameof(exception)); + } + + if (ErrorCount >= MaxAllowedErrors - 1) + { + EnsureMaxErrorsReachedRecorded(); + return false; + } + + ErrorCount++; + AddModelErrorCore(key, exception); + return true; + } + + /// + /// Adds the specified to the instance + /// that is associated with the specified . If the maximum number of allowed + /// errors has already been recorded, ensures that a exception is + /// recorded instead. + /// + /// The key of the to add errors to. + /// The to add. Some exception types will be replaced with + /// a descriptive error message. + /// The associated with the model. + public void AddModelError(string key, Exception exception, ModelMetadata metadata) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (exception == null) + { + throw new ArgumentNullException(nameof(exception)); + } + + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + TryAddModelError(key, exception, metadata); + } + + /// + /// Attempts to add the specified to the + /// instance that is associated with the specified . If the maximum number of allowed + /// errors has already been recorded, ensures that a exception is + /// recorded instead. + /// + /// The key of the to add errors to. + /// The to add. Some exception types will be replaced with + /// a descriptive error message. + /// The associated with the model. + /// + /// True if the given error was added, false if the error was ignored. + /// See . + /// + public bool TryAddModelError(string key, Exception exception, ModelMetadata metadata) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (exception == null) + { + throw new ArgumentNullException(nameof(exception)); + } + + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + if (ErrorCount >= MaxAllowedErrors - 1) + { + EnsureMaxErrorsReachedRecorded(); + return false; + } + + if (exception is FormatException || exception is OverflowException) + { + // Convert FormatExceptions and OverflowExceptions to Invalid value messages. + TryGetValue(key, out var entry); + + // Not using metadata.GetDisplayName() or a single resource to avoid strange messages like + // "The value '' is not valid." (when no value was provided, not even an empty string) and + // "The supplied value is invalid for Int32." (when error is for an element or parameter). + var messageProvider = metadata.ModelBindingMessageProvider; + var name = metadata.DisplayName ?? metadata.PropertyName; + string errorMessage; + if (entry == null && name == null) + { + errorMessage = messageProvider.NonPropertyUnknownValueIsInvalidAccessor(); + } + else if (entry == null) + { + errorMessage = messageProvider.UnknownValueIsInvalidAccessor(name); + } + else if (name == null) + { + errorMessage = messageProvider.NonPropertyAttemptedValueIsInvalidAccessor(entry.AttemptedValue); + } + else + { + errorMessage = messageProvider.AttemptedValueIsInvalidAccessor(entry.AttemptedValue, name); + } + + return TryAddModelError(key, errorMessage); + } + else if (exception is InputFormatterException && !string.IsNullOrEmpty(exception.Message)) + { + // InputFormatterException is a signal that the message is safe to expose to clients + return TryAddModelError(key, exception.Message); + } + + ErrorCount++; + AddModelErrorCore(key, exception); + return true; + } + + /// + /// Adds the specified to the instance + /// that is associated with the specified . If the maximum number of allowed + /// errors has already been recorded, ensures that a exception is + /// recorded instead. + /// + /// The key of the to add errors to. + /// The error message to add. + public void AddModelError(string key, string errorMessage) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (errorMessage == null) + { + throw new ArgumentNullException(nameof(errorMessage)); + } + + TryAddModelError(key, errorMessage); + } + + /// + /// Attempts to add the specified to the + /// instance that is associated with the specified . If the maximum number of allowed + /// errors has already been recorded, ensures that a exception is + /// recorded instead. + /// + /// The key of the to add errors to. + /// The error message to add. + /// + /// True if the given error was added, false if the error was ignored. + /// See . + /// + public bool TryAddModelError(string key, string errorMessage) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (errorMessage == null) + { + throw new ArgumentNullException(nameof(errorMessage)); + } + + if (ErrorCount >= MaxAllowedErrors - 1) + { + EnsureMaxErrorsReachedRecorded(); + return false; + } + + ErrorCount++; + var modelState = GetOrAddNode(key); + Count += !modelState.IsContainerNode ? 0 : 1; + modelState.ValidationState = ModelValidationState.Invalid; + modelState.MarkNonContainerNode(); + modelState.Errors.Add(errorMessage); + + return true; + } + + /// + /// Returns the aggregate for items starting with the + /// specified . + /// + /// The key to look up model state errors for. + /// Returns if no entries are found for the specified + /// key, if at least one instance is found with one or more model + /// state errors; otherwise. + public ModelValidationState GetFieldValidationState(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + var item = GetNode(key); + return GetValidity(item) ?? ModelValidationState.Unvalidated; + } + + /// + /// Returns for the . + /// + /// The key to look up model state errors for. + /// Returns if no entry is found for the specified + /// key, if an instance is found with one or more model + /// state errors; otherwise. + public ModelValidationState GetValidationState(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (TryGetValue(key, out var validationState)) + { + return validationState.ValidationState; + } + + return ModelValidationState.Unvalidated; + } + + /// + /// Marks the for the entry with the specified + /// as . + /// + /// The key of the to mark as valid. + public void MarkFieldValid(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + var modelState = GetOrAddNode(key); + if (modelState.ValidationState == ModelValidationState.Invalid) + { + throw new InvalidOperationException(Resources.Validation_InvalidFieldCannotBeReset); + } + + Count += !modelState.IsContainerNode ? 0 : 1; + modelState.MarkNonContainerNode(); + modelState.ValidationState = ModelValidationState.Valid; + } + + /// + /// Marks the for the entry with the specified + /// as . + /// + /// The key of the to mark as skipped. + public void MarkFieldSkipped(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + var modelState = GetOrAddNode(key); + if (modelState.ValidationState == ModelValidationState.Invalid) + { + throw new InvalidOperationException(Resources.Validation_InvalidFieldCannotBeReset_ToSkipped); + } + + Count += !modelState.IsContainerNode ? 0 : 1; + modelState.MarkNonContainerNode(); + modelState.ValidationState = ModelValidationState.Skipped; + } + + /// + /// Copies the values from the specified into this instance, overwriting + /// existing values if keys are the same. + /// + /// The to copy values from. + public void Merge(ModelStateDictionary dictionary) + { + if (dictionary == null) + { + return; + } + + foreach (var source in dictionary) + { + var target = GetOrAddNode(source.Key); + Count += !target.IsContainerNode ? 0 : 1; + ErrorCount += source.Value.Errors.Count - target.Errors.Count; + target.Copy(source.Value); + target.MarkNonContainerNode(); + } + } + + /// + /// Sets the of and for + /// the with the specified . + /// + /// The key for the entry. + /// The raw value for the entry. + /// + /// The values of in a comma-separated . + /// + public void SetModelValue(string key, object rawValue, string attemptedValue) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + var modelState = GetOrAddNode(key); + Count += !modelState.IsContainerNode ? 0 : 1; + modelState.RawValue = rawValue; + modelState.AttemptedValue = attemptedValue; + modelState.MarkNonContainerNode(); + } + + /// + /// Sets the value for the with the specified . + /// + /// The key for the entry + /// + /// A with data for the entry. + /// + public void SetModelValue(string key, ValueProviderResult valueProviderResult) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + // Avoid creating a new array for rawValue if there's only one value. + object rawValue; + if (valueProviderResult == ValueProviderResult.None) + { + rawValue = null; + } + else if (valueProviderResult.Length == 1) + { + rawValue = valueProviderResult.Values[0]; + } + else + { + rawValue = valueProviderResult.Values.ToArray(); + } + + SetModelValue(key, rawValue, valueProviderResult.ToString()); + } + + /// + /// Clears entries that match the key that is passed as parameter. + /// + /// The key of to clear. + public void ClearValidationState(string key) + { + // If key is null or empty, clear all entries in the dictionary + // else just clear the ones that have key as prefix + var entries = FindKeysWithPrefix(key ?? string.Empty); + foreach (var entry in entries) + { + entry.Value.Errors.Clear(); + entry.Value.ValidationState = ModelValidationState.Unvalidated; + } + } + + private ModelStateNode GetNode(string key) + { + Debug.Assert(key != null); + + var current = _root; + if (key.Length > 0) + { + var match = default(MatchResult); + do + { + var subKey = FindNext(key, ref match); + current = current.GetNode(subKey); + + // Path not found, exit early + if (current == null) + { + break; + } + + } while (match.Type != Delimiter.None); + } + + return current; + } + + private ModelStateNode GetOrAddNode(string key) + { + Debug.Assert(key != null); + // For a key of the format, foo.bar[0].baz[qux] we'll create the following nodes: + // foo + // -> bar + // -> [0] + // -> baz + // -> [qux] + + var current = _root; + if (key.Length > 0) + { + var match = default(MatchResult); + do + { + var subKey = FindNext(key, ref match); + current = current.GetOrAddNode(subKey); + + } while (match.Type != Delimiter.None); + + if (current.Key == null) + { + // New Node - Set key + current.Key = key; + } + } + + return current; + } + + // Shared function factored out for clarity, force inlining to put back in + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static StringSegment FindNext(string key, ref MatchResult currentMatch) + { + var index = currentMatch.Index; + var matchType = Delimiter.None; + + for (; index < key.Length; index++) + { + var ch = key[index]; + if (ch == DelimiterDot) + { + matchType = Delimiter.Dot; + break; + } + else if (ch == DelimiterOpen) + { + matchType = Delimiter.OpenBracket; + break; + } + } + + var keyStart = currentMatch.Type == Delimiter.OpenBracket + ? currentMatch.Index - 1 + : currentMatch.Index; + + currentMatch.Type = matchType; + currentMatch.Index = index + 1; + + return new StringSegment(key, keyStart, index - keyStart); + } + + private static ModelValidationState? GetValidity(ModelStateNode node) + { + if (node == null) + { + return null; + } + + ModelValidationState? validationState = null; + if (!node.IsContainerNode) + { + validationState = ModelValidationState.Valid; + if (node.ValidationState == ModelValidationState.Unvalidated) + { + // If any entries of a field is unvalidated, we'll treat the tree as unvalidated. + return ModelValidationState.Unvalidated; + } + + if (node.ValidationState == ModelValidationState.Invalid) + { + validationState = node.ValidationState; + } + } + + if (node.ChildNodes != null) + { + for (var i = 0; i < node.ChildNodes.Count; i++) + { + var entryState = GetValidity(node.ChildNodes[i]); + + if (entryState == ModelValidationState.Unvalidated) + { + return entryState; + } + + if (validationState == null || entryState == ModelValidationState.Invalid) + { + validationState = entryState; + } + } + } + + return validationState; + } + + private void EnsureMaxErrorsReachedRecorded() + { + if (!HasRecordedMaxModelError) + { + var exception = new TooManyModelErrorsException(Resources.ModelStateDictionary_MaxModelStateErrors); + AddModelErrorCore(string.Empty, exception); + HasRecordedMaxModelError = true; + ErrorCount++; + } + } + + private void AddModelErrorCore(string key, Exception exception) + { + var modelState = GetOrAddNode(key); + Count += !modelState.IsContainerNode ? 0 : 1; + modelState.ValidationState = ModelValidationState.Invalid; + modelState.MarkNonContainerNode(); + modelState.Errors.Add(exception); + } + + /// + /// Removes all keys and values from this instance of . + /// + public void Clear() + { + Count = 0; + HasRecordedMaxModelError = false; + ErrorCount = 0; + _root.Reset(); + _root.ChildNodes?.Clear(); + } + + /// + public bool ContainsKey(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return !GetNode(key)?.IsContainerNode ?? false; + } + + /// + /// Removes the with the specified . + /// + /// The key. + /// true if the element is successfully removed; otherwise false. This method also + /// returns false if key was not found. + public bool Remove(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + var node = GetNode(key); + if (node?.IsContainerNode == false) + { + Count--; + ErrorCount -= node.Errors.Count; + node.Reset(); + return true; + } + + return false; + } + + /// + public bool TryGetValue(string key, out ModelStateEntry value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + var result = GetNode(key); + if (result?.IsContainerNode == false) + { + value = result; + return true; + } + + value = null; + return false; + } + + /// + /// Returns an enumerator that iterates through this instance of . + /// + /// An . + public Enumerator GetEnumerator() => new Enumerator(this, prefix: string.Empty); + + /// + IEnumerator> + IEnumerable>.GetEnumerator() => GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public static bool StartsWithPrefix(string prefix, string key) + { + if (prefix == null) + { + throw new ArgumentNullException(nameof(prefix)); + } + + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (prefix.Length == 0) + { + // Everything is prefixed by the empty string. + return true; + } + + if (prefix.Length > key.Length) + { + return false; // Not long enough. + } + + if (!key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + if (key.Length == prefix.Length) + { + // Exact match + return true; + } + + var charAfterPrefix = key[prefix.Length]; + if (charAfterPrefix == '.' || charAfterPrefix == '[') + { + return true; + } + + return false; + } + + public PrefixEnumerable FindKeysWithPrefix(string prefix) + { + if (prefix == null) + { + throw new ArgumentNullException(nameof(prefix)); + } + + return new PrefixEnumerable(this, prefix); + } + + private struct MatchResult + { + public Delimiter Type; + public int Index; + } + + private enum Delimiter + { + None = 0, + Dot, + OpenBracket + } + + [DebuggerDisplay("SubKey={SubKey}, Key={Key}, ValidationState={ValidationState}")] + private class ModelStateNode : ModelStateEntry + { + private bool _isContainerNode = true; + + public ModelStateNode(StringSegment subKey) + { + SubKey = subKey; + } + + public List ChildNodes { get; set; } + + public override IReadOnlyList Children => ChildNodes; + + public string Key { get; set; } + + public StringSegment SubKey { get; } + + public override bool IsContainerNode => _isContainerNode; + + public void MarkNonContainerNode() + { + _isContainerNode = false; + } + + public void Copy(ModelStateEntry entry) + { + RawValue = entry.RawValue; + AttemptedValue = entry.AttemptedValue; + Errors.Clear(); + for (var i = 0; i < entry.Errors.Count; i++) + { + Errors.Add(entry.Errors[i]); + } + + ValidationState = entry.ValidationState; + } + + public void Reset() + { + _isContainerNode = true; + RawValue = null; + AttemptedValue = null; + ValidationState = ModelValidationState.Unvalidated; + Errors.Clear(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ModelStateNode GetNode(StringSegment subKey) + { + ModelStateNode modelStateNode = null; + if (subKey.Length == 0) + { + modelStateNode = this; + } + else if (ChildNodes != null) + { + var index = BinarySearch(subKey); + if (index >= 0) + { + modelStateNode = ChildNodes[index]; + } + } + + return modelStateNode; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ModelStateNode GetOrAddNode(StringSegment subKey) + { + ModelStateNode modelStateNode; + if (subKey.Length == 0) + { + modelStateNode = this; + } + else if (ChildNodes == null) + { + ChildNodes = new List(1); + modelStateNode = new ModelStateNode(subKey); + ChildNodes.Add(modelStateNode); + } + else + { + var index = BinarySearch(subKey); + if (index >= 0) + { + modelStateNode = ChildNodes[index]; + } + else + { + modelStateNode = new ModelStateNode(subKey); + ChildNodes.Insert(~index, modelStateNode); + } + } + + return modelStateNode; + } + + public override ModelStateEntry GetModelStateForProperty(string propertyName) + => GetNode(new StringSegment(propertyName)); + + private int BinarySearch(StringSegment searchKey) + { + Debug.Assert(ChildNodes != null); + + var low = 0; + var high = ChildNodes.Count - 1; + while (low <= high) + { + var mid = low + ((high - low) / 2); + var midKey = ChildNodes[mid].SubKey; + var result = midKey.Length - searchKey.Length; + if (result == 0) + { + result = string.Compare( + midKey.Buffer, + midKey.Offset, + searchKey.Buffer, + searchKey.Offset, + searchKey.Length, + StringComparison.OrdinalIgnoreCase); + } + + if (result == 0) + { + return mid; + } + if (result < 0) + { + low = mid + 1; + } + else + { + high = mid - 1; + } + } + + return ~low; + } + } + + public struct PrefixEnumerable : IEnumerable> + { + private readonly ModelStateDictionary _dictionary; + private readonly string _prefix; + + public PrefixEnumerable(ModelStateDictionary dictionary, string prefix) + { + if (dictionary == null) + { + throw new ArgumentNullException(nameof(dictionary)); + } + + if (prefix == null) + { + throw new ArgumentNullException(nameof(prefix)); + } + + _dictionary = dictionary; + _prefix = prefix; + } + + public Enumerator GetEnumerator() => new Enumerator(_dictionary, _prefix); + + IEnumerator> + IEnumerable>.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public struct Enumerator : IEnumerator> + { + private readonly ModelStateNode _rootNode; + private ModelStateNode _modelStateNode; + private List _nodes; + private int _index; + private bool _visitedRoot; + + public Enumerator(ModelStateDictionary dictionary, string prefix) + { + if (dictionary == null) + { + throw new ArgumentNullException(nameof(dictionary)); + } + + if (prefix == null) + { + throw new ArgumentNullException(nameof(prefix)); + } + + _index = -1; + _rootNode = dictionary.GetNode(prefix); + _modelStateNode = null; + _nodes = null; + _visitedRoot = false; + } + + public KeyValuePair Current => + new KeyValuePair(_modelStateNode.Key, _modelStateNode); + + object IEnumerator.Current => Current; + + public void Dispose() + { + } + + public bool MoveNext() + { + if (_rootNode == null) + { + return false; + } + + if (!_visitedRoot) + { + // Visit the root node + _visitedRoot = true; + if (_rootNode.ChildNodes?.Count > 0) + { + _nodes = new List { _rootNode }; + } + + if (!_rootNode.IsContainerNode) + { + _modelStateNode = _rootNode; + return true; + } + } + + if (_nodes == null) + { + return false; + } + + while (_nodes.Count > 0) + { + var node = _nodes[0]; + if (_index == node.ChildNodes.Count - 1) + { + // We've exhausted the current sublist. + _nodes.RemoveAt(0); + _index = -1; + continue; + } + else + { + _index++; + } + + var currentChild = node.ChildNodes[_index]; + if (currentChild.ChildNodes?.Count > 0) + { + _nodes.Add(currentChild); + } + + if (!currentChild.IsContainerNode) + { + _modelStateNode = currentChild; + return true; + } + } + + return false; + } + + public void Reset() + { + _index = -1; + _nodes.Clear(); + _visitedRoot = false; + _modelStateNode = null; + } + } + + public struct KeyEnumerable : IEnumerable + { + private readonly ModelStateDictionary _dictionary; + + public KeyEnumerable(ModelStateDictionary dictionary) + { + _dictionary = dictionary; + } + + public KeyEnumerator GetEnumerator() => new KeyEnumerator(_dictionary, prefix: string.Empty); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public struct KeyEnumerator : IEnumerator + { + private Enumerator _prefixEnumerator; + + public KeyEnumerator(ModelStateDictionary dictionary, string prefix) + { + _prefixEnumerator = new Enumerator(dictionary, prefix); + Current = null; + } + + public string Current { get; private set; } + + object IEnumerator.Current => Current; + + public void Dispose() => _prefixEnumerator.Dispose(); + + public bool MoveNext() + { + var result = _prefixEnumerator.MoveNext(); + if (result) + { + var current = _prefixEnumerator.Current; + Current = current.Key; + } + else + { + Current = null; + } + + return result; + } + + public void Reset() + { + _prefixEnumerator.Reset(); + Current = null; + } + } + + public struct ValueEnumerable : IEnumerable + { + private readonly ModelStateDictionary _dictionary; + + public ValueEnumerable(ModelStateDictionary dictionary) + { + _dictionary = dictionary; + } + + public ValueEnumerator GetEnumerator() => new ValueEnumerator(_dictionary, prefix: string.Empty); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public struct ValueEnumerator : IEnumerator + { + private Enumerator _prefixEnumerator; + + public ValueEnumerator(ModelStateDictionary dictionary, string prefix) + { + _prefixEnumerator = new Enumerator(dictionary, prefix); + Current = null; + } + + public ModelStateEntry Current { get; private set; } + + object IEnumerator.Current => Current; + + public void Dispose() => _prefixEnumerator.Dispose(); + + public bool MoveNext() + { + var result = _prefixEnumerator.MoveNext(); + if (result) + { + var current = _prefixEnumerator.Current; + Current = current.Value; + } + else + { + Current = null; + } + + return result; + } + + public void Reset() + { + _prefixEnumerator.Reset(); + Current = null; + } + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateEntry.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateEntry.cs new file mode 100644 index 0000000000..b73eab4f77 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelStateEntry.cs @@ -0,0 +1,75 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// An entry in a . + /// + public abstract class ModelStateEntry + { + private ModelErrorCollection _errors; + + /// + /// Gets the raw value from the request associated with this entry. + /// + public object RawValue { get; set; } + + /// + /// Gets the set of values contained in , joined into a comma-separated string. + /// + public string AttemptedValue { get; set; } + + /// + /// Gets the for this entry. + /// + public ModelErrorCollection Errors + { + get + { + if (_errors == null) + { + _errors = new ModelErrorCollection(); + } + return _errors; + } + } + + /// + /// Gets or sets the for this entry. + /// + public ModelValidationState ValidationState { get; set; } + + /// + /// Gets a value that determines if the current instance of is a container node. + /// Container nodes represent prefix nodes that aren't explicitly added to the + /// . + /// + public abstract bool IsContainerNode { get; } + + /// + /// Gets the for a sub-property with the specified + /// . + /// + /// The property name to lookup. + /// + /// The if a sub-property was found; otherwise . + /// + /// + /// This method returns any existing entry, even those with with value + /// . + /// + public abstract ModelStateEntry GetModelStateForProperty(string propertyName); + + /// + /// Gets the values for sub-properties. + /// + /// + /// This property returns all existing entries, even those with with value + /// . + /// + public abstract IReadOnlyList Children { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelValidationState.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelValidationState.cs new file mode 100644 index 0000000000..05cc0ee317 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelValidationState.cs @@ -0,0 +1,13 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding +{ + public enum ModelValidationState + { + Unvalidated, + Invalid, + Valid, + Skipped + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/TooManyModelErrorsException.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/TooManyModelErrorsException.cs new file mode 100644 index 0000000000..58f3cdbe42 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/TooManyModelErrorsException.cs @@ -0,0 +1,27 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// The that is thrown when too many model errors are encountered. + /// + public class TooManyModelErrorsException : Exception + { + /// + /// Creates a new instance of with the specified + /// exception . + /// + /// The message that describes the error. + public TooManyModelErrorsException(string message) + : base(message) + { + if (message == null) + { + throw new ArgumentNullException(nameof(message)); + } + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientModelValidationContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientModelValidationContext.cs new file mode 100644 index 0000000000..7d04881119 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientModelValidationContext.cs @@ -0,0 +1,35 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// The context for client-side model validation. + /// + public class ClientModelValidationContext : ModelValidationContextBase + { + /// + /// Create a new instance of . + /// + /// The for validation. + /// The for validation. + /// The to be used in validation. + /// The attributes dictionary for the HTML tag being rendered. + public ClientModelValidationContext( + ActionContext actionContext, + ModelMetadata metadata, + IModelMetadataProvider metadataProvider, + IDictionary attributes) + : base(actionContext, metadata, metadataProvider) + { + Attributes = attributes; + } + + /// + /// Gets the attributes dictionary for the HTML tag being rendered. + /// + public IDictionary Attributes { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientValidatorItem.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientValidatorItem.cs new file mode 100644 index 0000000000..e346509701 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientValidatorItem.cs @@ -0,0 +1,45 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Used to associate validators with instances + /// as part of . An should + /// inspect and set and + /// as appropriate. + /// + public class ClientValidatorItem + { + /// + /// Creates a new . + /// + public ClientValidatorItem() + { + } + + /// + /// Creates a new . + /// + /// The . + public ClientValidatorItem(object validatorMetadata) + { + ValidatorMetadata = validatorMetadata; + } + + /// + /// Gets the metadata associated with the . + /// + public object ValidatorMetadata { get; } + + /// + /// Gets or sets the . + /// + public IClientModelValidator Validator { get; set; } + + /// + /// Gets or sets a value indicating whether or not can be reused across requests. + /// + public bool IsReusable { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientValidatorProviderContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientValidatorProviderContext.cs new file mode 100644 index 0000000000..84b02119b3 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ClientValidatorProviderContext.cs @@ -0,0 +1,46 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// A context for . + /// + public class ClientValidatorProviderContext + { + /// + /// Creates a new . + /// + /// The for the model being validated. + /// + /// The list of s. + public ClientValidatorProviderContext(ModelMetadata modelMetadata, IList items) + { + ModelMetadata = modelMetadata; + Results = items; + } + + /// + /// Gets the . + /// + public ModelMetadata ModelMetadata { get; } + + /// + /// Gets the validator metadata. + /// + /// + /// This property provides convenience access to . + /// + public IReadOnlyList ValidatorMetadata => ModelMetadata.ValidatorMetadata; + + /// + /// Gets the list of instances. + /// instances should add the appropriate properties when + /// + /// is called. + /// + public IList Results { get; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IClientModelValidator.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IClientModelValidator.cs new file mode 100644 index 0000000000..6a46cec649 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IClientModelValidator.cs @@ -0,0 +1,10 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + public interface IClientModelValidator + { + void AddValidation(ClientModelValidationContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IClientModelValidatorProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IClientModelValidatorProvider.cs new file mode 100644 index 0000000000..adf01cf8f8 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IClientModelValidatorProvider.cs @@ -0,0 +1,18 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Provides a collection of s. + /// + public interface IClientModelValidatorProvider + { + /// + /// Creates set of s by updating + /// in . + /// + /// The associated with this call. + void CreateValidators(ClientValidatorProviderContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IModelValidator.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IModelValidator.cs new file mode 100644 index 0000000000..f2f0ae34ef --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IModelValidator.cs @@ -0,0 +1,22 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Validates a model value. + /// + public interface IModelValidator + { + /// + /// Validates the model value. + /// + /// The . + /// + /// A list of indicating the results of validating the model value. + /// + IEnumerable Validate(ModelValidationContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IModelValidatorProvider.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IModelValidatorProvider.cs new file mode 100644 index 0000000000..9ed1704ca9 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IModelValidatorProvider.cs @@ -0,0 +1,22 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Provides validators for a model value. + /// + public interface IModelValidatorProvider + { + /// + /// Creates the validators for . + /// + /// The . + /// + /// Implementations should add the instances to the appropriate + /// instance which should be added to + /// . + /// + void CreateValidators(ModelValidatorProviderContext context); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IPropertyValidationFilter.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IPropertyValidationFilter.cs new file mode 100644 index 0000000000..622b41f70c --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IPropertyValidationFilter.cs @@ -0,0 +1,22 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Contract for attributes that determine whether associated properties should be validated. When the attribute is + /// applied to a property, the validation system calls to determine whether to + /// validate that property. When applied to a type, the validation system calls + /// for each property that type defines to determine whether to validate it. + /// + public interface IPropertyValidationFilter + { + /// + /// Gets an indication whether the should be validated. + /// + /// to check. + /// containing . + /// true if should be validated; false otherwise. + bool ShouldValidateEntry(ValidationEntry entry, ValidationEntry parentEntry); + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IValidationStrategy.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IValidationStrategy.cs new file mode 100644 index 0000000000..4419957230 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/IValidationStrategy.cs @@ -0,0 +1,23 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Defines a strategy for enumerating the child entries of a model object which should be validated. + /// + public interface IValidationStrategy + { + /// + /// Gets an containing a for + /// each child entry of the model object to be validated. + /// + /// The associated with . + /// The model prefix associated with . + /// The model object. + /// An . + IEnumerator GetChildren(ModelMetadata metadata, string key, object model); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationContext.cs new file mode 100644 index 0000000000..78f48f32fb --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationContext.cs @@ -0,0 +1,41 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// A context object for . + /// + public class ModelValidationContext : ModelValidationContextBase + { + /// + /// Create a new instance of . + /// + /// The for validation. + /// The for validation. + /// The to be used in validation. + /// The model container. + /// The model to be validated. + public ModelValidationContext( + ActionContext actionContext, + ModelMetadata modelMetadata, + IModelMetadataProvider metadataProvider, + object container, + object model) + : base(actionContext, modelMetadata, metadataProvider) + { + Container = container; + Model = model; + } + + /// + /// Gets the model object. + /// + public object Model { get; } + + /// + /// Gets the model container object. + /// + public object Container { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationContextBase.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationContextBase.cs new file mode 100644 index 0000000000..ea341ef62e --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationContextBase.cs @@ -0,0 +1,59 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// A common base class for and . + /// + public class ModelValidationContextBase + { + /// + /// Instantiates a new . + /// + /// The for this context. + /// The for this model. + /// The to be used by this context. + public ModelValidationContextBase( + ActionContext actionContext, + ModelMetadata modelMetadata, + IModelMetadataProvider metadataProvider) + { + if (actionContext == null) + { + throw new ArgumentNullException(nameof(actionContext)); + } + + if (modelMetadata == null) + { + throw new ArgumentNullException(nameof(modelMetadata)); + } + + if (metadataProvider == null) + { + throw new ArgumentNullException(nameof(metadataProvider)); + } + + ActionContext = actionContext; + ModelMetadata = modelMetadata; + MetadataProvider = metadataProvider; + } + + /// + /// Gets the . + /// + public ActionContext ActionContext { get; } + + /// + /// Gets the . + /// + public ModelMetadata ModelMetadata { get; } + + /// + /// Gets the . + /// + public IModelMetadataProvider MetadataProvider { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationResult.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationResult.cs new file mode 100644 index 0000000000..0d00621ed0 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidationResult.cs @@ -0,0 +1,18 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + public class ModelValidationResult + { + public ModelValidationResult(string memberName, string message) + { + MemberName = memberName ?? string.Empty; + Message = message ?? string.Empty; + } + + public string MemberName { get; } + + public string Message { get; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidatorProviderContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidatorProviderContext.cs new file mode 100644 index 0000000000..8076c82da4 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ModelValidatorProviderContext.cs @@ -0,0 +1,45 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// A context for . + /// + public class ModelValidatorProviderContext + { + /// + /// Creates a new . + /// + /// The . + /// The list of s. + public ModelValidatorProviderContext(ModelMetadata modelMetadata, IList items) + { + ModelMetadata = modelMetadata; + Results = items; + } + + /// + /// Gets the . + /// + public ModelMetadata ModelMetadata { get; set; } + + /// + /// Gets the validator metadata. + /// + /// + /// This property provides convenience access to . + /// + public IReadOnlyList ValidatorMetadata => ModelMetadata.ValidatorMetadata; + + /// + /// Gets the list of instances. instances + /// should add the appropriate properties when + /// + /// is called. + /// + public IList Results { get; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationEntry.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationEntry.cs new file mode 100644 index 0000000000..a873273ca7 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationEntry.cs @@ -0,0 +1,96 @@ +// 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; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Contains data needed for validating a child entry of a model object. See . + /// + public struct ValidationEntry + { + private object _model; + private Func _modelAccessor; + + /// + /// Creates a new . + /// + /// The associated with . + /// The model prefix associated with . + /// The model object. + public ValidationEntry(ModelMetadata metadata, string key, object model) + { + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + Metadata = metadata; + Key = key; + _model = model; + _modelAccessor = null; + } + + /// + /// Creates a new . + /// + /// The associated with the . + /// The model prefix associated with the . + /// A delegate that will return the . + public ValidationEntry(ModelMetadata metadata, string key, Func modelAccessor) + { + if (metadata == null) + { + throw new ArgumentNullException(nameof(metadata)); + } + + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (modelAccessor == null) + { + throw new ArgumentNullException(nameof(modelAccessor)); + } + + Metadata = metadata; + Key = key; + _model = null; + _modelAccessor = modelAccessor; + } + + /// + /// The model prefix associated with . + /// + public string Key { get; } + + /// + /// The associated with . + /// + public ModelMetadata Metadata { get; } + + /// + /// The model object. + /// + public object Model + { + get + { + if (_modelAccessor != null) + { + _model = _modelAccessor(); + _modelAccessor = null; + } + + return _model; + } + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationStateDictionary.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationStateDictionary.cs new file mode 100644 index 0000000000..11179b014d --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationStateDictionary.cs @@ -0,0 +1,154 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Used for tracking validation state to customize validation behavior for a model object. + /// + public class ValidationStateDictionary : + IDictionary, + IReadOnlyDictionary + { + private readonly Dictionary _inner; + + /// + /// Creates a new . + /// + public ValidationStateDictionary() + { + _inner = new Dictionary(ReferenceEqualityComparer.Instance); + } + + /// + public ValidationStateEntry this[object key] + { + get + { + TryGetValue(key, out var entry); + return entry; + } + + set + { + _inner[key] = value; + } + } + + /// + public int Count => _inner.Count; + + /// + public bool IsReadOnly => ((IDictionary)_inner).IsReadOnly; + + /// + public ICollection Keys => ((IDictionary)_inner).Keys; + + /// + public ICollection Values => ((IDictionary)_inner).Values; + + /// + IEnumerable IReadOnlyDictionary.Keys => + ((IReadOnlyDictionary)_inner).Keys; + + /// + IEnumerable IReadOnlyDictionary.Values => + ((IReadOnlyDictionary)_inner).Values; + + /// + public void Add(KeyValuePair item) + { + ((IDictionary)_inner).Add(item); + } + + /// + public void Add(object key, ValidationStateEntry value) + { + _inner.Add(key, value); + } + + /// + public void Clear() + { + _inner.Clear(); + } + + /// + public bool Contains(KeyValuePair item) + { + return ((IDictionary)_inner).Contains(item); + } + + /// + public bool ContainsKey(object key) + { + return _inner.ContainsKey(key); + } + + /// + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + ((IDictionary)_inner).CopyTo(array, arrayIndex); + } + + /// + public IEnumerator> GetEnumerator() + { + return ((IDictionary)_inner).GetEnumerator(); + } + + /// + public bool Remove(KeyValuePair item) + { + return _inner.Remove(item); + } + + /// + public bool Remove(object key) + { + return _inner.Remove(key); + } + + /// + public bool TryGetValue(object key, out ValidationStateEntry value) + { + return _inner.TryGetValue(key, out value); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return ((IDictionary)_inner).GetEnumerator(); + } + + private class ReferenceEqualityComparer : IEqualityComparer + { + private static readonly bool IsMono = Type.GetType("Mono.Runtime") != null; + + public static readonly ReferenceEqualityComparer Instance = new ReferenceEqualityComparer(); + + public new bool Equals(object x, object y) + { + return Object.ReferenceEquals(x, y); + } + + public int GetHashCode(object obj) + { + // RuntimeHelpers.GetHashCode sometimes crashes the runtime on Mono 4.0.4 + // See: https://github.com/aspnet/External/issues/45 + // The workaround here is to just not hash anything, and fall back to an equality check. + if (IsMono) + { + return 0; + } + + return RuntimeHelpers.GetHashCode(obj); + } + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationStateEntry.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationStateEntry.cs new file mode 100644 index 0000000000..970cbb8dfa --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidationStateEntry.cs @@ -0,0 +1,33 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// An entry in a . Records state information to override the default + /// behavior of validation for an object. + /// + public class ValidationStateEntry + { + /// + /// Gets or sets the model prefix associated with the entry. + /// + public string Key { get; set; } + + /// + /// Gets or sets the associated with the entry. + /// + public ModelMetadata Metadata { get; set; } + + /// + /// Gets or sets a value indicating whether the associated model object should be validated. + /// + public bool SuppressValidation { get; set; } + + /// + /// Gets or sets an for enumerating child entries of the associated + /// model object. + /// + public IValidationStrategy Strategy { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidatorItem.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidatorItem.cs new file mode 100644 index 0000000000..8592eeca71 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/Validation/ValidatorItem.cs @@ -0,0 +1,45 @@ +// 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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation +{ + /// + /// Used to associate validators with instances + /// as part of . An should + /// inspect and set and + /// as appropriate. + /// + public class ValidatorItem + { + /// + /// Creates a new . + /// + public ValidatorItem() + { + } + + /// + /// Creates a new . + /// + /// The . + public ValidatorItem(object validatorMetadata) + { + ValidatorMetadata = validatorMetadata; + } + + /// + /// Gets the metadata associated with the . + /// + public object ValidatorMetadata { get; } + + /// + /// Gets or sets the . + /// + public IModelValidator Validator { get; set; } + + /// + /// Gets or sets a value indicating whether or not can be reused across requests. + /// + public bool IsReusable { get; set; } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ValueProviderFactoryContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ValueProviderFactoryContext.cs new file mode 100644 index 0000000000..cf48d9072d --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ValueProviderFactoryContext.cs @@ -0,0 +1,40 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// A context for . + /// + public class ValueProviderFactoryContext + { + /// + /// Creates a new . + /// + /// The . + public ValueProviderFactoryContext(ActionContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + ActionContext = context; + } + + /// + /// Gets the associated with this context. + /// + public ActionContext ActionContext { get; } + + /// + /// Gets the list of instances. + /// instances should add the appropriate + /// instances to this list. + /// + public IList ValueProviders { get; } = new List(); + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ValueProviderResult.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ValueProviderResult.cs new file mode 100644 index 0000000000..c9bf19ad4c --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ValueProviderResult.cs @@ -0,0 +1,187 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.AspNetCore.Mvc.ModelBinding +{ + /// + /// Result of an operation. + /// + /// + /// + /// can represent a single submitted value or multiple submitted values. + /// + /// + /// Use to consume only a single value, regardless of whether a single value or + /// multiple values were submitted. + /// + /// + /// Treat as an to consume all values, + /// regardless of whether a single value or multiple values were submitted. + /// + /// + public struct ValueProviderResult : IEquatable, IEnumerable + { + private static readonly CultureInfo _invariantCulture = CultureInfo.InvariantCulture; + + /// + /// A that represents a lack of data. + /// + public static ValueProviderResult None = new ValueProviderResult(new string[0]); + + /// + /// Creates a new using . + /// + /// The submitted values. + public ValueProviderResult(StringValues values) + : this(values, _invariantCulture) + { + } + + /// + /// Creates a new . + /// + /// The submitted values. + /// The associated with this value. + public ValueProviderResult(StringValues values, CultureInfo culture) + { + Values = values; + Culture = culture ?? _invariantCulture; + } + + /// + /// Gets or sets the associated with the values. + /// + public CultureInfo Culture { get; } + + /// + /// Gets or sets the values. + /// + public StringValues Values { get; } + + /// + /// Gets the first value based on the order values were provided in the request. Use + /// to get a single value for processing regardless of whether a single or multiple values were provided + /// in the request. + /// + public string FirstValue + { + get + { + if (Values.Count == 0) + { + return null; + } + return Values[0]; + } + } + + /// + /// Gets the number of submitted values. + /// + public int Length => Values.Count; + + /// + public override bool Equals(object obj) + { + var other = obj as ValueProviderResult?; + return other.HasValue && Equals(other.Value); + } + + /// + public bool Equals(ValueProviderResult other) + { + if (Length != other.Length) + { + return false; + } + else + { + var x = Values; + var y = other.Values; + for (var i = 0; i < x.Count; i++) + { + if (!string.Equals(x[i], y[i], StringComparison.Ordinal)) + { + return false; + } + } + return true; + } + } + + /// + public override int GetHashCode() + { + return ToString().GetHashCode(); + } + + /// + public override string ToString() + { + return Values.ToString(); + } + + /// + /// Gets an for this . + /// + /// An . + public IEnumerator GetEnumerator() + { + return ((IEnumerable)Values).GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Converts the provided into a comma-separated string containing all + /// submitted values. + /// + /// The . + public static explicit operator string(ValueProviderResult result) + { + return result.Values; + } + + /// + /// Converts the provided into a an array of containing + /// all submitted values. + /// + /// The . + public static explicit operator string[](ValueProviderResult result) + { + return result.Values; + } + + /// + /// Compares two objects for equality. + /// + /// A . + /// A . + /// true if the values are equal, otherwise false. + public static bool operator ==(ValueProviderResult x, ValueProviderResult y) + { + return x.Equals(y); + } + + /// + /// Compares two objects for inequality. + /// + /// A . + /// A . + /// false if the values are equal, otherwise true. + public static bool operator !=(ValueProviderResult x, ValueProviderResult y) + { + return !x.Equals(y); + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Properties/AssemblyInfo.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3af3e8d9b2 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Properties/Resources.Designer.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..f19e063180 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Properties/Resources.Designer.cs @@ -0,0 +1,296 @@ +// +namespace Microsoft.AspNetCore.Mvc.Abstractions +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNetCore.Mvc.Abstractions.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// Value cannot be null or empty. + /// + internal static string ArgumentCannotBeNullOrEmpty + { + get => GetString("ArgumentCannotBeNullOrEmpty"); + } + + /// + /// Value cannot be null or empty. + /// + internal static string FormatArgumentCannotBeNullOrEmpty() + => GetString("ArgumentCannotBeNullOrEmpty"); + + /// + /// The ModelMetadata property must be set before accessing this property. + /// + internal static string ModelBindingContext_ModelMetadataMustBeSet + { + get => GetString("ModelBindingContext_ModelMetadataMustBeSet"); + } + + /// + /// The ModelMetadata property must be set before accessing this property. + /// + internal static string FormatModelBindingContext_ModelMetadataMustBeSet() + => GetString("ModelBindingContext_ModelMetadataMustBeSet"); + + /// + /// A field previously marked invalid should not be marked valid. + /// + internal static string Validation_InvalidFieldCannotBeReset + { + get => GetString("Validation_InvalidFieldCannotBeReset"); + } + + /// + /// A field previously marked invalid should not be marked valid. + /// + internal static string FormatValidation_InvalidFieldCannotBeReset() + => GetString("Validation_InvalidFieldCannotBeReset"); + + /// + /// A field previously marked invalid should not be marked skipped. + /// + internal static string Validation_InvalidFieldCannotBeReset_ToSkipped + { + get => GetString("Validation_InvalidFieldCannotBeReset_ToSkipped"); + } + + /// + /// A field previously marked invalid should not be marked skipped. + /// + internal static string FormatValidation_InvalidFieldCannotBeReset_ToSkipped() + => GetString("Validation_InvalidFieldCannotBeReset_ToSkipped"); + + /// + /// The maximum number of allowed model errors has been reached. + /// + internal static string ModelStateDictionary_MaxModelStateErrors + { + get => GetString("ModelStateDictionary_MaxModelStateErrors"); + } + + /// + /// The maximum number of allowed model errors has been reached. + /// + internal static string FormatModelStateDictionary_MaxModelStateErrors() + => GetString("ModelStateDictionary_MaxModelStateErrors"); + + /// + /// Body + /// + internal static string BindingSource_Body + { + get => GetString("BindingSource_Body"); + } + + /// + /// Body + /// + internal static string FormatBindingSource_Body() + => GetString("BindingSource_Body"); + + /// + /// Custom + /// + internal static string BindingSource_Custom + { + get => GetString("BindingSource_Custom"); + } + + /// + /// Custom + /// + internal static string FormatBindingSource_Custom() + => GetString("BindingSource_Custom"); + + /// + /// Form + /// + internal static string BindingSource_Form + { + get => GetString("BindingSource_Form"); + } + + /// + /// Form + /// + internal static string FormatBindingSource_Form() + => GetString("BindingSource_Form"); + + /// + /// Header + /// + internal static string BindingSource_Header + { + get => GetString("BindingSource_Header"); + } + + /// + /// Header + /// + internal static string FormatBindingSource_Header() + => GetString("BindingSource_Header"); + + /// + /// Services + /// + internal static string BindingSource_Services + { + get => GetString("BindingSource_Services"); + } + + /// + /// Services + /// + internal static string FormatBindingSource_Services() + => GetString("BindingSource_Services"); + + /// + /// ModelBinding + /// + internal static string BindingSource_ModelBinding + { + get => GetString("BindingSource_ModelBinding"); + } + + /// + /// ModelBinding + /// + internal static string FormatBindingSource_ModelBinding() + => GetString("BindingSource_ModelBinding"); + + /// + /// Path + /// + internal static string BindingSource_Path + { + get => GetString("BindingSource_Path"); + } + + /// + /// Path + /// + internal static string FormatBindingSource_Path() + => GetString("BindingSource_Path"); + + /// + /// Query + /// + internal static string BindingSource_Query + { + get => GetString("BindingSource_Query"); + } + + /// + /// Query + /// + internal static string FormatBindingSource_Query() + => GetString("BindingSource_Query"); + + /// + /// The provided binding source '{0}' is a composite. '{1}' requires that the source must represent a single type of input. + /// + internal static string BindingSource_CannotBeComposite + { + get => GetString("BindingSource_CannotBeComposite"); + } + + /// + /// The provided binding source '{0}' is a composite. '{1}' requires that the source must represent a single type of input. + /// + internal static string FormatBindingSource_CannotBeComposite(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("BindingSource_CannotBeComposite"), p0, p1); + + /// + /// The provided binding source '{0}' is not a request-based binding source. '{1}' requires that the source must represent data from an HTTP request. + /// + internal static string BindingSource_MustBeFromRequest + { + get => GetString("BindingSource_MustBeFromRequest"); + } + + /// + /// The provided binding source '{0}' is not a request-based binding source. '{1}' requires that the source must represent data from an HTTP request. + /// + internal static string FormatBindingSource_MustBeFromRequest(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("BindingSource_MustBeFromRequest"), p0, p1); + + /// + /// The provided binding source '{0}' is a greedy data source. '{1}' does not support greedy data sources. + /// + internal static string BindingSource_CannotBeGreedy + { + get => GetString("BindingSource_CannotBeGreedy"); + } + + /// + /// The provided binding source '{0}' is a greedy data source. '{1}' does not support greedy data sources. + /// + internal static string FormatBindingSource_CannotBeGreedy(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("BindingSource_CannotBeGreedy"), p0, p1); + + /// + /// The provided binding source '{0}' is not a greedy data source. '{1}' only supports greedy data sources. + /// + internal static string BindingSource_MustBeGreedy + { + get => GetString("BindingSource_MustBeGreedy"); + } + + /// + /// The provided binding source '{0}' is not a greedy data source. '{1}' only supports greedy data sources. + /// + internal static string FormatBindingSource_MustBeGreedy(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("BindingSource_MustBeGreedy"), p0, p1); + + /// + /// Special + /// + internal static string BindingSource_Special + { + get => GetString("BindingSource_Special"); + } + + /// + /// Special + /// + internal static string FormatBindingSource_Special() + => GetString("BindingSource_Special"); + + /// + /// FormFile + /// + internal static string BindingSource_FormFile + { + get => GetString("BindingSource_FormFile"); + } + + /// + /// FormFile + /// + internal static string FormatBindingSource_FormFile() + => GetString("BindingSource_FormFile"); + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Resources.resx b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Resources.resx new file mode 100644 index 0000000000..224ec4161d --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Resources.resx @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Value cannot be null or empty. + + + The ModelMetadata property must be set before accessing this property. + + + A field previously marked invalid should not be marked valid. + + + A field previously marked invalid should not be marked skipped. + + + The maximum number of allowed model errors has been reached. + + + Body + + + Custom + + + Form + + + Header + + + Services + + + ModelBinding + + + Path + + + Query + + + The provided binding source '{0}' is a composite. '{1}' requires that the source must represent a single type of input. + + + The provided binding source '{0}' is not a request-based binding source. '{1}' requires that the source must represent data from an HTTP request. + + + The provided binding source '{0}' is a greedy data source. '{1}' does not support greedy data sources. + + + The provided binding source '{0}' is not a greedy data source. '{1}' only supports greedy data sources. + + + Special + + + FormFile + + \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/AttributeRouteInfo.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/AttributeRouteInfo.cs new file mode 100644 index 0000000000..5531b44ced --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/AttributeRouteInfo.cs @@ -0,0 +1,40 @@ +// 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 Microsoft.AspNetCore.Mvc.Routing +{ + /// + /// Represents the routing information for an action that is attribute routed. + /// + public class AttributeRouteInfo + { + /// + /// The route template. May be null if the action has no attribute routes. + /// + public string Template { get; set; } + + /// + /// Gets the order of the route associated with a given action. This property determines + /// the order in which routes get executed. Routes with a lower order value are tried first. In case a route + /// doesn't specify a value, it gets a default order of 0. + /// + public int Order { get; set; } + + /// + /// Gets the name of the route associated with a given action. This property can be used + /// to generate a link by referring to the route by name instead of attempting to match a + /// route by provided route data. + /// + public string Name { get; set; } + + /// + /// Gets or sets a value that determines if the route entry associated with this model participates in link generation. + /// + public bool SuppressLinkGeneration { get; set; } + + /// + /// Gets or sets a value that determines if the route entry associated with this model participates in path matching (inbound routing). + /// + public bool SuppressPathMatching { get; set; } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/UrlActionContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/UrlActionContext.cs new file mode 100644 index 0000000000..8260b6b680 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/UrlActionContext.cs @@ -0,0 +1,67 @@ +// 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 Microsoft.AspNetCore.Mvc.Routing +{ + /// + /// Context object to be used for the URLs that generates. + /// + public class UrlActionContext + { + /// + /// The name of the action method that uses to generate URLs. + /// + public string Action + { + get; + set; + } + + /// + /// The name of the controller that uses to generate URLs. + /// + public string Controller + { + get; + set; + } + + /// + /// The object that contains the route values that + /// uses to generate URLs. + /// + public object Values + { + get; + set; + } + + /// + /// The protocol for the URLs that generates, + /// such as "http" or "https" + /// + public string Protocol + { + get; + set; + } + + /// + /// The host name for the URLs that generates. + /// + public string Host + { + get; + set; + } + + /// + /// The fragment for the URLs that generates. + /// + public string Fragment + { + get; + set; + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/UrlRouteContext.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/UrlRouteContext.cs new file mode 100644 index 0000000000..706414f958 --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/Routing/UrlRouteContext.cs @@ -0,0 +1,58 @@ +// 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 Microsoft.AspNetCore.Mvc.Routing +{ + /// + /// Context object to be used for the URLs that generates. + /// + public class UrlRouteContext + { + /// + /// The name of the route that uses to generate URLs. + /// + public string RouteName + { + get; + set; + } + + /// + /// The object that contains the route values that + /// uses to generate URLs. + /// + public object Values + { + get; + set; + } + + /// + /// The protocol for the URLs that generates, + /// such as "http" or "https" + /// + public string Protocol + { + get; + set; + } + + /// + /// The host name for the URLs that generates. + /// + public string Host + { + get; + set; + } + + /// + /// The fragment for the URLs that generates. + /// + public string Fragment + { + get; + set; + } + } +} \ No newline at end of file diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/baseline.netcore.json b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/baseline.netcore.json new file mode 100644 index 0000000000..a3ee847f2f --- /dev/null +++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.Abstractions/baseline.netcore.json @@ -0,0 +1,9358 @@ +{ + "AssemblyIdentity": "Microsoft.AspNetCore.Mvc.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", + "Types": [ + { + "Name": "Microsoft.AspNetCore.Mvc.ActionContext", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ActionDescriptor", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ActionDescriptor", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HttpContext", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Http.HttpContext", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_HttpContext", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Http.HttpContext" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ModelState", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_RouteData", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Routing.RouteData", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_RouteData", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Routing.RouteData" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "actionContext", + "Type": "Microsoft.AspNetCore.Mvc.ActionContext" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "httpContext", + "Type": "Microsoft.AspNetCore.Http.HttpContext" + }, + { + "Name": "routeData", + "Type": "Microsoft.AspNetCore.Routing.RouteData" + }, + { + "Name": "actionDescriptor", + "Type": "Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "httpContext", + "Type": "Microsoft.AspNetCore.Http.HttpContext" + }, + { + "Name": "routeData", + "Type": "Microsoft.AspNetCore.Routing.RouteData" + }, + { + "Name": "actionDescriptor", + "Type": "Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor" + }, + { + "Name": "modelState", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.IActionResult", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "ExecuteResultAsync", + "Parameters": [ + { + "Name": "context", + "Type": "Microsoft.AspNetCore.Mvc.ActionContext" + } + ], + "ReturnType": "System.Threading.Tasks.Task", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.IUrlHelper", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ActionContext", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ActionContext", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Action", + "Parameters": [ + { + "Name": "actionContext", + "Type": "Microsoft.AspNetCore.Mvc.Routing.UrlActionContext" + } + ], + "ReturnType": "System.String", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Content", + "Parameters": [ + { + "Name": "contentPath", + "Type": "System.String" + } + ], + "ReturnType": "System.String", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "IsLocalUrl", + "Parameters": [ + { + "Name": "url", + "Type": "System.String" + } + ], + "ReturnType": "System.Boolean", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "RouteUrl", + "Parameters": [ + { + "Name": "routeContext", + "Type": "Microsoft.AspNetCore.Mvc.Routing.UrlRouteContext" + } + ], + "ReturnType": "System.String", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Link", + "Parameters": [ + { + "Name": "routeName", + "Type": "System.String" + }, + { + "Name": "values", + "Type": "System.Object" + } + ], + "ReturnType": "System.String", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.Routing.AttributeRouteInfo", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Template", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Template", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Order", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Order", + "Parameters": [ + { + "Name": "value", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Name", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Name", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_SuppressLinkGeneration", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_SuppressLinkGeneration", + "Parameters": [ + { + "Name": "value", + "Type": "System.Boolean" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_SuppressPathMatching", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_SuppressPathMatching", + "Parameters": [ + { + "Name": "value", + "Type": "System.Boolean" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.Routing.UrlActionContext", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Action", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Action", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Controller", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Controller", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Values", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Values", + "Parameters": [ + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Protocol", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Protocol", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Host", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Host", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Fragment", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Fragment", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.Routing.UrlRouteContext", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_RouteName", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_RouteName", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Values", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Values", + "Parameters": [ + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Protocol", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Protocol", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Host", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Host", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Fragment", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Fragment", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_BindingSource", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_BindingSource", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BinderModelName", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_BinderModelName", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BinderType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_BinderType", + "Parameters": [ + { + "Name": "value", + "Type": "System.Type" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_PropertyFilterProvider", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_PropertyFilterProvider", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_RequestPredicate", + "Parameters": [], + "ReturnType": "System.Func", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_RequestPredicate", + "Parameters": [ + { + "Name": "value", + "Type": "System.Func" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetBindingInfo", + "Parameters": [ + { + "Name": "attributes", + "Type": "System.Collections.Generic.IEnumerable" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetBindingInfo", + "Parameters": [ + { + "Name": "attributes", + "Type": "System.Collections.Generic.IEnumerable" + }, + { + "Name": "modelMetadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "TryApplyBindingInfo", + "Parameters": [ + { + "Name": "modelMetadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + } + ], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "other", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "System.IEquatable" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_DisplayName", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Id", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsGreedy", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsFromRequest", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CanAcceptDataFrom", + "Parameters": [ + { + "Name": "bindingSource", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Equals", + "Parameters": [ + { + "Name": "other", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + } + ], + "ReturnType": "System.Boolean", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.IEquatable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Equals", + "Parameters": [ + { + "Name": "obj", + "Type": "System.Object" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetHashCode", + "Parameters": [], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "op_Equality", + "Parameters": [ + { + "Name": "s1", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + }, + { + "Name": "s2", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + } + ], + "ReturnType": "System.Boolean", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "op_Inequality", + "Parameters": [ + { + "Name": "s1", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + }, + { + "Name": "s2", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + } + ], + "ReturnType": "System.Boolean", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "id", + "Type": "System.String" + }, + { + "Name": "displayName", + "Type": "System.String" + }, + { + "Name": "isGreedy", + "Type": "System.Boolean" + }, + { + "Name": "isFromRequest", + "Type": "System.Boolean" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Body", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Custom", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Form", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Header", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "ModelBinding", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Path", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Query", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Services", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "Special", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "FormFile", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.CompositeBindingSource", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Create", + "Parameters": [ + { + "Name": "bindingSources", + "Type": "System.Collections.Generic.IEnumerable" + }, + { + "Name": "displayName", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.CompositeBindingSource", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BindingSources", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IEnumerable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CanAcceptDataFrom", + "Parameters": [ + { + "Name": "bindingSource", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.EnumGroupAndName", + "Visibility": "Public", + "Kind": "Struct", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Group", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Name", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "group", + "Type": "System.String" + }, + { + "Name": "name", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "group", + "Type": "System.String" + }, + { + "Name": "name", + "Type": "System.Func" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IBinderTypeProviderMetadata", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_BinderType", + "Parameters": [], + "ReturnType": "System.Type", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_BindingSource", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "BindModelAsync", + "Parameters": [ + { + "Name": "bindingContext", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext" + } + ], + "ReturnType": "System.Threading.Tasks.Task", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "GetBinder", + "Parameters": [ + { + "Name": "context", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "GetMetadataForType", + "Parameters": [ + { + "Name": "modelType", + "Type": "System.Type" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetMetadataForProperties", + "Parameters": [ + { + "Name": "modelType", + "Type": "System.Type" + } + ], + "ReturnType": "System.Collections.Generic.IEnumerable", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Name", + "Parameters": [], + "ReturnType": "System.String", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_PropertyFilter", + "Parameters": [], + "ReturnType": "System.Func", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IRequestPredicateProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_RequestPredicate", + "Parameters": [], + "ReturnType": "System.Func", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "ContainsPrefix", + "Parameters": [ + { + "Name": "prefix", + "Type": "System.String" + } + ], + "ReturnType": "System.Boolean", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetValue", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateValueProviderAsync", + "Parameters": [ + { + "Name": "context", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext" + } + ], + "ReturnType": "System.Threading.Tasks.Task", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateBinder", + "Parameters": [ + { + "Name": "metadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "CreateBinder", + "Parameters": [ + { + "Name": "metadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "bindingInfo", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BindingInfo", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Metadata", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_MetadataProvider", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Services", + "Parameters": [], + "ReturnType": "System.IServiceProvider", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Protected", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ActionContext", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ActionContext", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ActionContext", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ActionContext" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BinderModelName", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_BinderModelName", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BindingSource", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_BindingSource", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_FieldName", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_FieldName", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HttpContext", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Http.HttpContext", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsTopLevelObject", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_IsTopLevelObject", + "Parameters": [ + { + "Name": "value", + "Type": "System.Boolean" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Model", + "Parameters": [], + "ReturnType": "System.Object", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Model", + "Parameters": [ + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ModelMetadata", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ModelMetadata", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ModelName", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ModelName", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ModelState", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ModelState", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ModelType", + "Parameters": [], + "ReturnType": "System.Type", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_PropertyFilter", + "Parameters": [], + "ReturnType": "System.Func", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_PropertyFilter", + "Parameters": [ + { + "Name": "value", + "Type": "System.Func" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidationState", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ValidationState", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValueProvider", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ValueProvider", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Result", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Result", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult" + } + ], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "EnterNestedScope", + "Parameters": [ + { + "Name": "modelMetadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "fieldName", + "Type": "System.String" + }, + { + "Name": "modelName", + "Type": "System.String" + }, + { + "Name": "model", + "Type": "System.Object" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext+NestedScope", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "EnterNestedScope", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext+NestedScope", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ExitNestedScope", + "Parameters": [], + "ReturnType": "System.Void", + "Virtual": true, + "Abstract": true, + "Visibility": "Protected", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Protected", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult", + "Visibility": "Public", + "Kind": "Struct", + "Sealed": true, + "ImplementedInterfaces": [ + "System.IEquatable" + ], + "Members": [ + { + "Kind": "Method", + "Name": "Failed", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Success", + "Parameters": [ + { + "Name": "model", + "Type": "System.Object" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Model", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsModelSet", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Equals", + "Parameters": [ + { + "Name": "obj", + "Type": "System.Object" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetHashCode", + "Parameters": [], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Equals", + "Parameters": [ + { + "Name": "other", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult" + } + ], + "ReturnType": "System.Boolean", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.IEquatable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ToString", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "op_Equality", + "Parameters": [ + { + "Name": "x", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult" + }, + { + "Name": "y", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult" + } + ], + "ReturnType": "System.Boolean", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "op_Inequality", + "Parameters": [ + { + "Name": "x", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult" + }, + { + "Name": "y", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult" + } + ], + "ReturnType": "System.Boolean", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelError", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Exception", + "Parameters": [], + "ReturnType": "System.Exception", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ErrorMessage", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "exception", + "Type": "System.Exception" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "exception", + "Type": "System.Exception" + }, + { + "Name": "errorMessage", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "errorMessage", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelErrorCollection", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "System.Collections.ObjectModel.Collection", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Add", + "Parameters": [ + { + "Name": "exception", + "Type": "System.Exception" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Add", + "Parameters": [ + { + "Name": "errorMessage", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "ImplementedInterfaces": [ + "System.IEquatable", + "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_ContainerType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ContainerMetadata", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_MetadataKind", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataKind", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ModelType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Name", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ParameterName", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_PropertyName", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Identity", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity", + "Visibility": "Protected", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_AdditionalValues", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyDictionary", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Properties", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelPropertyCollection", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BinderModelName", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BinderType", + "Parameters": [], + "ReturnType": "System.Type", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_BindingSource", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ConvertEmptyStringToNull", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_DataTypeName", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Description", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_DisplayFormatString", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_DisplayName", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EditFormatString", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ElementMetadata", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EnumGroupedDisplayNamesAndValues", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IEnumerable>", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_EnumNamesAndValues", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyDictionary", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HasNonDefaultEditFormat", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HtmlEncode", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HideSurroundingHtml", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsBindingAllowed", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsBindingRequired", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsEnum", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsFlagsEnum", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsReadOnly", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsRequired", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ModelBindingMessageProvider", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelBindingMessageProvider", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Order", + "Parameters": [], + "ReturnType": "System.Int32", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Placeholder", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_NullDisplayText", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_PropertyFilterProvider", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ShowForDisplay", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ShowForEdit", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_SimpleDisplayProperty", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_TemplateHint", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_PropertyValidationFilter", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IPropertyValidationFilter", + "Virtual": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidateChildren", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidatorMetadata", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyList", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ElementType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsComplexType", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsNullableValueType", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsCollectionType", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsEnumerableType", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsReferenceOrNullableType", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_UnderlyingOrModelType", + "Parameters": [], + "ReturnType": "System.Type", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_PropertyGetter", + "Parameters": [], + "ReturnType": "System.Func", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_PropertySetter", + "Parameters": [], + "ReturnType": "System.Action", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetDisplayName", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Equals", + "Parameters": [ + { + "Name": "other", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + } + ], + "ReturnType": "System.Boolean", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.IEquatable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Equals", + "Parameters": [ + { + "Name": "obj", + "Type": "System.Object" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetHashCode", + "Parameters": [], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetMetadataForType", + "Parameters": [ + { + "Name": "modelType", + "Type": "System.Type" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetMetadataForProperties", + "Parameters": [ + { + "Name": "modelType", + "Type": "System.Type" + } + ], + "ReturnType": "System.Collections.Generic.IEnumerable", + "Virtual": true, + "ImplementedInterface": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "identity", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity" + } + ], + "Visibility": "Protected", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "DefaultOrder", + "Parameters": [], + "ReturnType": "System.Int32", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadataProvider", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "ImplementedInterfaces": [ + "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider" + ], + "Members": [ + { + "Kind": "Method", + "Name": "GetMetadataForProperties", + "Parameters": [ + { + "Name": "modelType", + "Type": "System.Type" + } + ], + "ReturnType": "System.Collections.Generic.IEnumerable", + "Virtual": true, + "Abstract": true, + "ImplementedInterface": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetMetadataForType", + "Parameters": [ + { + "Name": "modelType", + "Type": "System.Type" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Virtual": true, + "Abstract": true, + "ImplementedInterface": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetMetadataForParameter", + "Parameters": [ + { + "Name": "parameter", + "Type": "System.Reflection.ParameterInfo" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Protected", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelPropertyCollection", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "System.Collections.ObjectModel.ReadOnlyCollection", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Item", + "Parameters": [ + { + "Name": "propertyName", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "properties", + "Type": "System.Collections.Generic.IEnumerable" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "System.Collections.Generic.IReadOnlyDictionary" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_Count", + "Parameters": [], + "ReturnType": "System.Int32", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.Collections.Generic.IReadOnlyCollection>", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Root", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_MaxAllowedErrors", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_MaxAllowedErrors", + "Parameters": [ + { + "Name": "value", + "Type": "System.Int32" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_HasReachedMaxErrors", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ErrorCount", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Keys", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+KeyEnumerable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Values", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+ValueEnumerable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsValid", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidationState", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Item", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.Collections.Generic.IReadOnlyDictionary", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "TryAddModelException", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "exception", + "Type": "System.Exception" + } + ], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AddModelError", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "exception", + "Type": "System.Exception" + }, + { + "Name": "metadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "TryAddModelError", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "exception", + "Type": "System.Exception" + }, + { + "Name": "metadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + } + ], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "AddModelError", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "errorMessage", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "TryAddModelError", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "errorMessage", + "Type": "System.String" + } + ], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetFieldValidationState", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetValidationState", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "MarkFieldValid", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "MarkFieldSkipped", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Merge", + "Parameters": [ + { + "Name": "dictionary", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "SetModelValue", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "rawValue", + "Type": "System.Object" + }, + { + "Name": "attemptedValue", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "SetModelValue", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "valueProviderResult", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ClearValidationState", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Clear", + "Parameters": [], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ContainsKey", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "System.Boolean", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.Collections.Generic.IReadOnlyDictionary", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Remove", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "TryGetValue", + "Parameters": [ + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry", + "Direction": "Out" + } + ], + "ReturnType": "System.Boolean", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.Collections.Generic.IReadOnlyDictionary", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetEnumerator", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+Enumerator", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "StartsWithPrefix", + "Parameters": [ + { + "Name": "prefix", + "Type": "System.String" + }, + { + "Name": "key", + "Type": "System.String" + } + ], + "ReturnType": "System.Boolean", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "FindKeysWithPrefix", + "Parameters": [ + { + "Name": "prefix", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+PrefixEnumerable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "maxAllowedErrors", + "Type": "System.Int32" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "dictionary", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "DefaultMaxAllowedErrors", + "Parameters": [], + "ReturnType": "System.Int32", + "Static": true, + "ReadOnly": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry", + "Visibility": "Public", + "Kind": "Class", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_RawValue", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_RawValue", + "Parameters": [ + { + "Name": "value", + "Type": "System.Object" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_AttemptedValue", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_AttemptedValue", + "Parameters": [ + { + "Name": "value", + "Type": "System.String" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Errors", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelErrorCollection", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidationState", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ValidationState", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsContainerNode", + "Parameters": [], + "ReturnType": "System.Boolean", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetModelStateForProperty", + "Parameters": [ + { + "Name": "propertyName", + "Type": "System.String" + } + ], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Children", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyList", + "Virtual": true, + "Abstract": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Protected", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState", + "Visibility": "Public", + "Kind": "Enumeration", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Field", + "Name": "Unvalidated", + "Parameters": [], + "GenericParameter": [], + "Literal": "0" + }, + { + "Kind": "Field", + "Name": "Invalid", + "Parameters": [], + "GenericParameter": [], + "Literal": "1" + }, + { + "Kind": "Field", + "Name": "Valid", + "Parameters": [], + "GenericParameter": [], + "Literal": "2" + }, + { + "Kind": "Field", + "Name": "Skipped", + "Parameters": [], + "GenericParameter": [], + "Literal": "3" + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.TooManyModelErrorsException", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "System.Exception", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "message", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ActionContext", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ActionContext", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValueProviders", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IList", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "context", + "Type": "Microsoft.AspNetCore.Mvc.ActionContext" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult", + "Visibility": "Public", + "Kind": "Struct", + "Sealed": true, + "ImplementedInterfaces": [ + "System.IEquatable", + "System.Collections.Generic.IEnumerable" + ], + "Members": [ + { + "Kind": "Method", + "Name": "get_Culture", + "Parameters": [], + "ReturnType": "System.Globalization.CultureInfo", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Values", + "Parameters": [], + "ReturnType": "Microsoft.Extensions.Primitives.StringValues", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_FirstValue", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Length", + "Parameters": [], + "ReturnType": "System.Int32", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Equals", + "Parameters": [ + { + "Name": "obj", + "Type": "System.Object" + } + ], + "ReturnType": "System.Boolean", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "Equals", + "Parameters": [ + { + "Name": "other", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult" + } + ], + "ReturnType": "System.Boolean", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.IEquatable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetHashCode", + "Parameters": [], + "ReturnType": "System.Int32", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "ToString", + "Parameters": [], + "ReturnType": "System.String", + "Virtual": true, + "Override": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "GetEnumerator", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IEnumerator", + "Sealed": true, + "Virtual": true, + "ImplementedInterface": "System.Collections.Generic.IEnumerable", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "op_Explicit", + "Parameters": [ + { + "Name": "result", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult" + } + ], + "ReturnType": "System.String", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "op_Explicit", + "Parameters": [ + { + "Name": "result", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult" + } + ], + "ReturnType": "System.String[]", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "op_Equality", + "Parameters": [ + { + "Name": "x", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult" + }, + { + "Name": "y", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult" + } + ], + "ReturnType": "System.Boolean", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "op_Inequality", + "Parameters": [ + { + "Name": "x", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult" + }, + { + "Name": "y", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult" + } + ], + "ReturnType": "System.Boolean", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "values", + "Type": "Microsoft.Extensions.Primitives.StringValues" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "values", + "Type": "Microsoft.Extensions.Primitives.StringValues" + }, + { + "Name": "culture", + "Type": "System.Globalization.CultureInfo" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Field", + "Name": "None", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult", + "Static": true, + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContextBase", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Attributes", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IDictionary", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "actionContext", + "Type": "Microsoft.AspNetCore.Mvc.ActionContext" + }, + { + "Name": "metadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "metadataProvider", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider" + }, + { + "Name": "attributes", + "Type": "System.Collections.Generic.IDictionary" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientValidatorItem", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ValidatorMetadata", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Validator", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidator", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_Validator", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidator" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_IsReusable", + "Parameters": [], + "ReturnType": "System.Boolean", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_IsReusable", + "Parameters": [ + { + "Name": "value", + "Type": "System.Boolean" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "validatorMetadata", + "Type": "System.Object" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientValidatorProviderContext", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ModelMetadata", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidatorMetadata", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyList", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Results", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IList", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "modelMetadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "items", + "Type": "System.Collections.Generic.IList" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidator", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "AddValidation", + "Parameters": [ + { + "Name": "context", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidatorProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateValidators", + "Parameters": [ + { + "Name": "context", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientValidatorProviderContext" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidator", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "Validate", + "Parameters": [ + { + "Name": "context", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContext" + } + ], + "ReturnType": "System.Collections.Generic.IEnumerable", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidatorProvider", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "CreateValidators", + "Parameters": [ + { + "Name": "context", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidatorProviderContext" + } + ], + "ReturnType": "System.Void", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IPropertyValidationFilter", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "ShouldValidateEntry", + "Parameters": [ + { + "Name": "entry", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry" + }, + { + "Name": "parentEntry", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry" + } + ], + "ReturnType": "System.Boolean", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IValidationStrategy", + "Visibility": "Public", + "Kind": "Interface", + "Abstract": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "GetChildren", + "Parameters": [ + { + "Name": "metadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "model", + "Type": "System.Object" + } + ], + "ReturnType": "System.Collections.Generic.IEnumerator", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContext", + "Visibility": "Public", + "Kind": "Class", + "BaseType": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContextBase", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Model", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Container", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "actionContext", + "Type": "Microsoft.AspNetCore.Mvc.ActionContext" + }, + { + "Name": "modelMetadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "metadataProvider", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider" + }, + { + "Name": "container", + "Type": "System.Object" + }, + { + "Name": "model", + "Type": "System.Object" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContextBase", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ActionContext", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ActionContext", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ModelMetadata", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_MetadataProvider", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "actionContext", + "Type": "Microsoft.AspNetCore.Mvc.ActionContext" + }, + { + "Name": "modelMetadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "metadataProvider", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationResult", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_MemberName", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Message", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "memberName", + "Type": "System.String" + }, + { + "Name": "message", + "Type": "System.String" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidatorProviderContext", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_ModelMetadata", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "set_ModelMetadata", + "Parameters": [ + { + "Name": "value", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + } + ], + "ReturnType": "System.Void", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_ValidatorMetadata", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IReadOnlyList", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Results", + "Parameters": [], + "ReturnType": "System.Collections.Generic.IList", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "modelMetadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "items", + "Type": "System.Collections.Generic.IList" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry", + "Visibility": "Public", + "Kind": "Struct", + "Sealed": true, + "ImplementedInterfaces": [], + "Members": [ + { + "Kind": "Method", + "Name": "get_Key", + "Parameters": [], + "ReturnType": "System.String", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Metadata", + "Parameters": [], + "ReturnType": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Method", + "Name": "get_Model", + "Parameters": [], + "ReturnType": "System.Object", + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "metadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "model", + "Type": "System.Object" + } + ], + "Visibility": "Public", + "GenericParameter": [] + }, + { + "Kind": "Constructor", + "Name": ".ctor", + "Parameters": [ + { + "Name": "metadata", + "Type": "Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata" + }, + { + "Name": "key", + "Type": "System.String" + }, + { + "Name": "modelAccessor", + "Type": "System.Func" + } + ], + "Visibility": "Public", + "GenericParameter": [] + } + ], + "GenericParameters": [] + }, + { + "Name": "Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary", + "Visibility": "Public", + "Kind": "Class", + "ImplementedInterfaces": [ + "System.Collections.Generic.IDictionary", + "System.Collections.Generic.IReadOnlyDictionary
Message from TempData: @Message
+ /// /Views/Default/Index.html + /// ~/Index.html + ///
+ /// ../Index.html + /// http://www.contoso.com/ + /// http://localhost/Index.html + ///
MaxAllowedErrors - 1