[Fixes #3624] MVC functional test cleanup (part 2)
This commit is contained in:
parent
3a7c9c73ed
commit
57b88baad0
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24711.0
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
|
||||
EndProject
|
||||
|
|
@ -85,6 +85,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.TestDi
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MvcSandbox", "samples\MvcSandbox\MvcSandbox.xproj", "{14ED4476-9F24-4776-8417-EA6927F6C9C9}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "UrlHelperSample.Web", "samples\UrlHelperSample.Web\UrlHelperSample.Web.xproj", "{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -493,6 +495,18 @@ Global
|
|||
{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
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -533,5 +547,6 @@ Global
|
|||
{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}
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
60
Mvc.sln
60
Mvc.sln
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24711.0
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
|
||||
EndProject
|
||||
|
|
@ -54,8 +54,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ContentNegotiationWebSite",
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "FiltersWebSite", "test\WebSites\FiltersWebSite\FiltersWebSite.xproj", "{1976AC4A-FEA4-4587-A158-D9F79736D2B6}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "UrlHelperWebSite", "test\WebSites\UrlHelperWebSite\UrlHelperWebSite.xproj", "{A192E504-2881-41DC-90D1-B7F1DD1134E8}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ApiExplorerWebSite", "test\WebSites\ApiExplorerWebSite\ApiExplorerWebSite.xproj", "{61061528-071E-424E-965A-07BCC2F02672}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "VersioningWebSite", "test\WebSites\VersioningWebSite\VersioningWebSite.xproj", "{C6304029-78C8-4604-99BE-2078DCA1DD36}"
|
||||
|
|
@ -98,12 +96,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ActionConstraintsWebSite",
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "CustomRouteWebSite", "test\WebSites\CustomRouteWebSite\CustomRouteWebSite.xproj", "{364EC3C6-C9DB-45E0-A0F2-1EE61E4B429B}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ResponseCacheWebSite", "test\WebSites\ResponseCacheWebSite\ResponseCacheWebSite.xproj", "{BDEEBE09-C0C4-433C-B0B8-8478C9776996}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "XmlFormattersWebSite", "test\WebSites\XmlFormattersWebSite\XmlFormattersWebSite.xproj", "{C3123A70-41C4-4122-AD1C-D35DF8958DD7}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ValidationWebSite", "test\WebSites\ValidationWebSite\ValidationWebSite.xproj", "{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "FormatFilterWebSite", "test\WebSites\FormatFilterWebSite\FormatFilterWebSite.xproj", "{AC9BE567-540E-4C70-90C2-AAF021307A80}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ControllersFromServicesWebSite", "test\WebSites\ControllersFromServicesWebSite\ControllersFromServicesWebSite.xproj", "{983741B2-4424-4ED1-9B03-7675A67230C8}"
|
||||
|
|
@ -168,6 +162,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.TestDi
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MvcSandbox", "samples\MvcSandbox\MvcSandbox.xproj", "{14ED4476-9F24-4776-8417-EA6927F6C9C9}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "UrlHelperSample.Web", "samples\UrlHelperSample.Web\UrlHelperSample.Web.xproj", "{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -368,16 +364,6 @@ Global
|
|||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.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
|
||||
|
|
@ -604,18 +590,6 @@ Global
|
|||
{364EC3C6-C9DB-45E0-A0F2-1EE61E4B429B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{364EC3C6-C9DB-45E0-A0F2-1EE61E4B429B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{364EC3C6-C9DB-45E0-A0F2-1EE61E4B429B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996}.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
|
||||
|
|
@ -628,18 +602,6 @@ Global
|
|||
{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
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AC9BE567-540E-4C70-90C2-AAF021307A80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AC9BE567-540E-4C70-90C2-AAF021307A80}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AC9BE567-540E-4C70-90C2-AAF021307A80}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -1023,6 +985,18 @@ Global
|
|||
{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
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -1048,7 +1022,6 @@ Global
|
|||
{EE1AB716-F102-4CA3-AD2C-214A44B459A0} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{1976AC4A-FEA4-4587-A158-D9F79736D2B6} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{A192E504-2881-41DC-90D1-B7F1DD1134E8} = {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}
|
||||
|
|
@ -1070,9 +1043,7 @@ Global
|
|||
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{AF210F69-9D31-43AF-AC3A-CD366E252218} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{364EC3C6-C9DB-45E0-A0F2-1EE61E4B429B} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{BDEEBE09-C0C4-433C-B0B8-8478C9776996} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{C3123A70-41C4-4122-AD1C-D35DF8958DD7} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{87AB84B2-22C1-43C6-BB8A-1D327B446FB0} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{AC9BE567-540E-4C70-90C2-AAF021307A80} = {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}
|
||||
|
|
@ -1105,5 +1076,6 @@ Global
|
|||
{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}
|
||||
{73F095D2-D0BD-4D03-BC17-D7A5EF0C0191} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
/// <autosync enabled="true" />
|
||||
/// <reference path="../gulpfile.js" />
|
||||
/// <reference path="js/site.js" />
|
||||
/// <reference path="lib/bootstrap/dist/js/bootstrap.js" />
|
||||
/// <reference path="lib/jquery/dist/jquery.js" />
|
||||
/// <reference path="lib/jquery-validation/dist/jquery.validate.js" />
|
||||
/// <reference path="lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js" />
|
||||
|
|
|
|||
|
|
@ -1,7 +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.
|
||||
|
||||
namespace UrlHelperWebSite
|
||||
namespace UrlHelperSample.Web
|
||||
{
|
||||
public class AppOptions
|
||||
{
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace UrlHelperWebSite.Controllers
|
||||
namespace UrlHelperSample.Web.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
|
||||
namespace UrlHelperWebSite.Controllers
|
||||
namespace UrlHelperSample.Web.Controllers
|
||||
{
|
||||
[Route("api/[controller]/{id?}", Name = "SimplePocoApi")]
|
||||
public class SimplePocoController
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// 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.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
|
||||
namespace UrlHelperSample.Web
|
||||
{
|
||||
/// <summary>
|
||||
/// Following are some of the scenarios exercised here:
|
||||
/// 1. Based on configuration, generate Content urls pointing to local or a CDN server
|
||||
/// 2. Based on configuration, generate lower case urls
|
||||
/// </summary>
|
||||
public class CustomUrlHelper : UrlHelper
|
||||
{
|
||||
private readonly AppOptions _options;
|
||||
|
||||
public CustomUrlHelper(ActionContext actionContext, AppOptions options)
|
||||
: base(actionContext)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Depending on config data, generates an absolute url pointing to a CDN server
|
||||
/// or falls back to the default behavior
|
||||
/// </summary>
|
||||
/// <param name="contentPath">The virtual path of the content.</param>
|
||||
/// <returns>The absolute url.</returns>
|
||||
public override string Content(string contentPath)
|
||||
{
|
||||
if (_options.ServeCDNContent
|
||||
&& contentPath.StartsWith("~/", StringComparison.Ordinal))
|
||||
{
|
||||
var segment = new PathString(contentPath.Substring(1));
|
||||
|
||||
return ConvertToLowercaseUrl(_options.CDNServerBaseUrl + segment);
|
||||
}
|
||||
|
||||
return ConvertToLowercaseUrl(base.Content(contentPath));
|
||||
}
|
||||
|
||||
public override string RouteUrl(UrlRouteContext routeContext)
|
||||
{
|
||||
return ConvertToLowercaseUrl(base.RouteUrl(routeContext));
|
||||
}
|
||||
|
||||
public override string Action(UrlActionContext actionContext)
|
||||
{
|
||||
return ConvertToLowercaseUrl(base.Action(actionContext));
|
||||
}
|
||||
|
||||
private string ConvertToLowercaseUrl(string url)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(url)
|
||||
&& _options.GenerateLowercaseUrls)
|
||||
{
|
||||
return url.ToLowerInvariant();
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
|
||||
namespace UrlHelperSample.Web
|
||||
{
|
||||
public class CustomUrlHelperFactory : IUrlHelperFactory
|
||||
{
|
||||
private readonly AppOptions _options;
|
||||
|
||||
public CustomUrlHelperFactory(IOptions<AppOptions> options)
|
||||
{
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
public IUrlHelper GetUrlHelper(ActionContext context)
|
||||
{
|
||||
return new CustomUrlHelper(context, _options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,34 +2,35 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ValidationWebSite
|
||||
namespace UrlHelperSample.Web
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
// Set up application services
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<AppOptions>(optionsSetup =>
|
||||
{
|
||||
optionsSetup.ServeCDNContent = true;
|
||||
optionsSetup.CDNServerBaseUrl = "http://cdn.contoso.com";
|
||||
optionsSetup.GenerateLowercaseUrls = true;
|
||||
});
|
||||
|
||||
// Add MVC services to the services container
|
||||
services.AddMvc();
|
||||
|
||||
services.AddSingleton<IUrlHelperFactory, CustomUrlHelperFactory>();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseCultureReplacer();
|
||||
|
||||
// Set up file serving for JavaScript files.
|
||||
app.UseFileServer();
|
||||
|
||||
app.UseErrorReporter();
|
||||
|
||||
// Add MVC to the request pipeline
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
routes.MapRoute(
|
||||
name: "default",
|
||||
template: "{controller}/{action}/{id?}");
|
||||
routes.MapRoute("Default", "{controller=Home}/{action=Index}");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>87ab84b2-22c1-43c6-bb8a-1d327b446fb0</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
<ProjectGuid>73f095d2-d0bd-4d03-bc17-d7a5ef0c0191</ProjectGuid>
|
||||
<RootNamespace>UrlHelperSample.Web</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>49635</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"commands": {
|
||||
"weblistener": "Microsoft.AspNet.Server.WebListener",
|
||||
"web": "Microsoft.AspNet.Server.Kestrel"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
||||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
UrlHelperWebSite
|
||||
UrlHelperSample.Web
|
||||
===
|
||||
|
||||
This web site illustrates how to register a `CustomURLHelper` which can based on configuration, generate content
|
||||
|
|
@ -3,8 +3,13 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.AspNet.Mvc.Abstractions;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -181,6 +186,126 @@ namespace Microsoft.AspNet.Mvc
|
|||
Assert.NotNull(filter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResponseCache_SetsAllHeaders()
|
||||
{
|
||||
// Arrange
|
||||
var responseCache = new ResponseCacheAttribute()
|
||||
{
|
||||
Duration = 100,
|
||||
Location = ResponseCacheLocation.Any,
|
||||
VaryByHeader = "Accept"
|
||||
};
|
||||
var filter = (ResponseCacheFilter)responseCache.CreateInstance(GetServiceProvider(cacheProfiles: null));
|
||||
var context = GetActionExecutingContext(filter);
|
||||
|
||||
// Act
|
||||
filter.OnActionExecuting(context);
|
||||
|
||||
// Assert
|
||||
var response = context.HttpContext.Response;
|
||||
StringValues values;
|
||||
Assert.True(response.Headers.TryGetValue("Cache-Control", out values));
|
||||
var data = Assert.Single(values);
|
||||
AssertHeaderEquals("public, max-age=100", data);
|
||||
Assert.True(response.Headers.TryGetValue("Vary", out values));
|
||||
data = Assert.Single(values);
|
||||
Assert.Equal("Accept", data);
|
||||
}
|
||||
|
||||
public static TheoryData<ResponseCacheAttribute, string> CacheControlData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<ResponseCacheAttribute, string>
|
||||
{
|
||||
{
|
||||
new ResponseCacheAttribute() { Duration = 100, Location = ResponseCacheLocation.Any },
|
||||
"public, max-age=100"
|
||||
},
|
||||
{
|
||||
new ResponseCacheAttribute() { Duration = 100, Location = ResponseCacheLocation.Client },
|
||||
"max-age=100, private"
|
||||
},
|
||||
{
|
||||
new ResponseCacheAttribute() { NoStore = true, Duration = 0 },
|
||||
"no-store"
|
||||
},
|
||||
{
|
||||
new ResponseCacheAttribute()
|
||||
{
|
||||
NoStore = true,
|
||||
Duration = 0,
|
||||
Location = ResponseCacheLocation.None
|
||||
},
|
||||
"no-store, no-cache"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(CacheControlData))]
|
||||
public void ResponseCache_SetsDifferentCacheControlHeaders(
|
||||
ResponseCacheAttribute responseCacheAttribute,
|
||||
string expected)
|
||||
{
|
||||
// Arrange
|
||||
var filter = (ResponseCacheFilter)responseCacheAttribute.CreateInstance(
|
||||
GetServiceProvider(cacheProfiles: null));
|
||||
var context = GetActionExecutingContext(filter);
|
||||
|
||||
// Act
|
||||
filter.OnActionExecuting(context);
|
||||
|
||||
// Assert
|
||||
StringValues values;
|
||||
Assert.True(context.HttpContext.Response.Headers.TryGetValue("Cache-Control", out values));
|
||||
var data = Assert.Single(values);
|
||||
AssertHeaderEquals(expected, data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetsCacheControlPublicByDefault()
|
||||
{
|
||||
// Arrange
|
||||
var responseCacheAttribute = new ResponseCacheAttribute() { Duration = 40 };
|
||||
var filter = (ResponseCacheFilter)responseCacheAttribute.CreateInstance(
|
||||
GetServiceProvider(cacheProfiles: null));
|
||||
var context = GetActionExecutingContext(filter);
|
||||
|
||||
// Act
|
||||
filter.OnActionExecuting(context);
|
||||
|
||||
// Assert
|
||||
StringValues values;
|
||||
Assert.True(context.HttpContext.Response.Headers.TryGetValue("Cache-Control", out values));
|
||||
var data = Assert.Single(values);
|
||||
AssertHeaderEquals("public, max-age=40", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ThrowsWhenDurationIsNotSet()
|
||||
{
|
||||
// Arrange
|
||||
var responseCacheAttribute = new ResponseCacheAttribute()
|
||||
{
|
||||
VaryByHeader = "Accept"
|
||||
};
|
||||
var filter = (ResponseCacheFilter)responseCacheAttribute.CreateInstance(
|
||||
GetServiceProvider(cacheProfiles: null));
|
||||
var context = GetActionExecutingContext(filter);
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
filter.OnActionExecuting(context);
|
||||
});
|
||||
Assert.Equal(
|
||||
"If the 'NoStore' property is not set to true, 'Duration' property must be specified.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
private IServiceProvider GetServiceProvider(Dictionary<string, CacheProfile> cacheProfiles)
|
||||
{
|
||||
var serviceProvider = new Mock<IServiceProvider>();
|
||||
|
|
@ -199,5 +324,22 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
return serviceProvider.Object;
|
||||
}
|
||||
|
||||
private ActionExecutingContext GetActionExecutingContext(params IFilterMetadata[] filters)
|
||||
{
|
||||
return new ActionExecutingContext(
|
||||
new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor()),
|
||||
filters?.ToList() ?? new List<IFilterMetadata>(),
|
||||
new Dictionary<string, object>(),
|
||||
new object());
|
||||
}
|
||||
|
||||
private void AssertHeaderEquals(string expected, string actual)
|
||||
{
|
||||
// OrderBy is used because the order of the results may vary depending on the platform / client.
|
||||
Assert.Equal(
|
||||
expected.Split(',').Select(p => p.Trim()).OrderBy(item => item, StringComparer.Ordinal),
|
||||
actual.Split(',').Select(p => p.Trim()).OrderBy(item => item, StringComparer.Ordinal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Net;
|
||||
|
|
@ -15,11 +15,11 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
/// 1. Based on configuration, generate Content urls pointing to local or a CDN server
|
||||
/// 2. Based on configuration, generate lower case urls
|
||||
/// </summary>
|
||||
public class CustomUrlHelperTests : IClassFixture<MvcTestFixture<UrlHelperWebSite.Startup>>
|
||||
public class CustomUrlHelperTests : IClassFixture<MvcTestFixture<UrlHelperSample.Web.Startup>>
|
||||
{
|
||||
private const string _cdnServerBaseUrl = "http://cdn.contoso.com";
|
||||
|
||||
public CustomUrlHelperTests(MvcTestFixture<UrlHelperWebSite.Startup> fixture)
|
||||
public CustomUrlHelperTests(MvcTestFixture<UrlHelperSample.Web.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
}
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
{
|
||||
public class ModelMetadataAttributeTest : IClassFixture<MvcTestFixture<ValidationWebSite.Startup>>
|
||||
{
|
||||
public ModelMetadataAttributeTest(MvcTestFixture<ValidationWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_ValidBaseClass_EmptyResponseBody()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Name\": \"MVC\", \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 21, \"ProductDetails\": {\"Detail1\": \"d1\"," +
|
||||
" \"Detail2\": \"d2\", \"Detail3\": \"d3\"}}";
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/ValidateProductViewModelIncludingMetadata";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal("{}", body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidPropertiesAndSubPropertiesOnBaseClass_ReturnsErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Price\": 2, \"ProductDetails\": {\"Detail1\": \"d1\"}}";
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/ValidateProductViewModelIncludingMetadata";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
|
||||
Assert.Equal(6, json.Count);
|
||||
Assert.Equal("CompanyName cannot be null or empty.", json["CompanyName"]);
|
||||
Assert.Equal("The field Price must be between 20 and 100.", json["Price"]);
|
||||
// Mono issue - https://github.com/aspnet/External/issues/19
|
||||
Assert.Equal(PlatformNormalizer.NormalizeContent("The Category field is required."), json["Category"]);
|
||||
Assert.Equal(PlatformNormalizer.NormalizeContent("The Contact Us field is required."), json["Contact"]);
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Detail2 field is required."),
|
||||
json["ProductDetails.Detail2"]);
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Detail3 field is required."),
|
||||
json["ProductDetails.Detail3"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidComplexTypePropertyOnBaseClass_ReturnsErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Contact\":\"4255678765\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 21 }";
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/ValidateProductViewModelIncludingMetadata";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
|
||||
Assert.Equal(1, json.Count);
|
||||
// Mono issue - https://github.com/aspnet/External/issues/19
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The ProductDetails field is required."),
|
||||
json["ProductDetails"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidClassAttributeOnBaseClass_ReturnsErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"UK\",\"Price\": 21, \"ProductDetails\": {\"Detail1\": \"d1\"," +
|
||||
" \"Detail2\": \"d2\", \"Detail3\": \"d3\"}}";
|
||||
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/ValidateProductViewModelIncludingMetadata";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
|
||||
Assert.Equal(1, json.Count);
|
||||
Assert.Equal("Product must be made in the USA if it is not named.", json[""]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_ValidDerivedClass_EmptyResponseBody()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Name\": \"MVC\", \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\", \"Version\":\"2\"," +
|
||||
"\"DatePurchased\": \"/Date(1297246301973)/\", \"Price\" : \"110\" }";
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/ValidateSoftwareViewModelIncludingMetadata";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal("{}", body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidPropertiesOnDerivedClass_ReturnsErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Name\": \"MVC\", \"Contact\":\"425-895-9019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 2}";
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/ValidateSoftwareViewModelIncludingMetadata";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
|
||||
Assert.Equal(2, json.Count);
|
||||
Assert.Equal("The field Price must be between 100 and 200.", json["Price"]);
|
||||
Assert.Equal("The field Contact must be a string with a maximum length of 10.", json["Contact"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidClassAttributeOnBaseClassProduct_ReturnsErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"UK\",\"Version\":\"2\"," +
|
||||
"\"DatePurchased\": \"/Date(1297246301973)/\", \"Price\" : \"110\" }";
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/ValidateSoftwareViewModelIncludingMetadata";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
|
||||
Assert.Equal(1, json.Count);
|
||||
Assert.Equal("Product must be made in the USA if it is not named.", json[""]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,12 +10,12 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
{
|
||||
public class RemoteAttributeValidationTest : IClassFixture<MvcTestFixture<ValidationWebSite.Startup>>
|
||||
public class RemoteAttributeValidationTest : IClassFixture<MvcTestFixture<BasicWebSite.Startup>>
|
||||
{
|
||||
private static readonly Assembly _resourcesAssembly =
|
||||
typeof(RemoteAttributeValidationTest).GetTypeInfo().Assembly;
|
||||
|
||||
public RemoteAttributeValidationTest(MvcTestFixture<ValidationWebSite.Startup> fixture)
|
||||
public RemoteAttributeValidationTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
}
|
||||
|
|
@ -23,12 +23,12 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
public HttpClient Client { get; }
|
||||
|
||||
[Theory]
|
||||
[InlineData("Aria", "/Aria")]
|
||||
[InlineData("Area1", "/Area1")]
|
||||
[InlineData("Root", "")]
|
||||
public async Task RemoteAttribute_LeadsToExpectedValidationAttributes(string areaName, string pathSegment)
|
||||
{
|
||||
// Arrange
|
||||
var outputFile = "compiler/resources/ValidationWebSite." + areaName + ".RemoteAttribute_Home.Create.html";
|
||||
var outputFile = "compiler/resources/BasicWebSite." + areaName + ".RemoteAttribute_Home.Create.html";
|
||||
var expectedContent =
|
||||
await ResourceFile.ReadResourceAsync(_resourcesAssembly, outputFile, sourceFile: false);
|
||||
var url = "http://localhost" + pathSegment + "/RemoteAttribute_Home/Create";
|
||||
|
|
@ -55,9 +55,9 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
|
||||
[Theory]
|
||||
[InlineData("", "\"/RemoteAttribute_Verify/IsIdAvailable rejects Joe1.\"")]
|
||||
[InlineData("/Aria", "false")]
|
||||
[InlineData("/AnotherAria",
|
||||
"\"/AnotherAria/RemoteAttribute_Verify/IsIdAvailable rejects 'Joe4' with 'Joe1', 'Joe2', and 'Joe3'.\"")]
|
||||
[InlineData("/Area1", "false")]
|
||||
[InlineData("/Area2",
|
||||
"\"/Area2/RemoteAttribute_Verify/IsIdAvailable rejects 'Joe4' with 'Joe1', 'Joe2', and 'Joe3'.\"")]
|
||||
public async Task RemoteAttribute_VerificationAction_GetReturnsExpectedJson(
|
||||
string pathSegment,
|
||||
string expectedContent)
|
||||
|
|
@ -79,7 +79,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
|
||||
[Theory]
|
||||
[InlineData("", "\"/RemoteAttribute_Verify/IsIdAvailable rejects Jane1.\"")]
|
||||
[InlineData("/Aria", "false")]
|
||||
[InlineData("/Area1", "false")]
|
||||
public async Task RemoteAttribute_VerificationAction_PostReturnsExpectedJson(
|
||||
string pathSegment,
|
||||
string expectedContent)
|
||||
|
|
|
|||
|
|
@ -1,295 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
{
|
||||
public class ResponseCacheTest : IClassFixture<MvcTestFixture<ResponseCacheWebSite.Startup>>
|
||||
{
|
||||
public ResponseCacheTest(MvcTestFixture<ResponseCacheWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCache_SetsAllHeaders()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheHeaders/Index");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=100", data);
|
||||
data = Assert.Single(response.Headers.GetValues("Vary"));
|
||||
Assert.Equal("Accept", data);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CacheControlData
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] { "http://localhost/CacheHeaders/PublicCache", "public, max-age=100" };
|
||||
yield return new object[] { "http://localhost/CacheHeaders/ClientCache", "max-age=100, private" };
|
||||
yield return new object[] { "http://localhost/CacheHeaders/NoStore", "no-store" };
|
||||
yield return new object[] { "http://localhost/CacheHeaders/NoCacheAtAll", "no-store, no-cache" };
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(CacheControlData))]
|
||||
public async Task ResponseCache_SetsDifferentCacheControlHeaders(string url, string expected)
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync(url);
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals(expected, data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SetsHeadersForAllActionsOfClass()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response1 = await Client.GetAsync("http://localhost/ClassLevelCache/GetHelloWorld");
|
||||
var response2 = await Client.GetAsync("http://localhost/ClassLevelCache/GetFooBar");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response1.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=100", data);
|
||||
data = Assert.Single(response1.Headers.GetValues("Vary"));
|
||||
Assert.Equal("Accept", data);
|
||||
|
||||
data = Assert.Single(response2.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=100", data);
|
||||
data = Assert.Single(response2.Headers.GetValues("Vary"));
|
||||
Assert.Equal("Accept", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HeadersSetInActionOverridesTheOnesInClass()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/ClassLevelCache/ConflictExistingHeader");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=20", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HeadersToNotCacheAParticularAction()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/ClassLevelCache/DoNotCacheThisAction");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("no-store, no-cache", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClassLevelHeadersAreUnsetByActionLevelHeaders()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/ClassLevelNoStore/CacheThisAction");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Vary"));
|
||||
Assert.Equal("Accept", data);
|
||||
data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=10", data);
|
||||
IEnumerable<string> pragmaValues;
|
||||
response.Headers.TryGetValues("Pragma", out pragmaValues);
|
||||
Assert.Null(pragmaValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SetsCacheControlPublicByDefault()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheHeaders/SetsCacheControlPublicByDefault");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=40", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ThrowsWhenDurationIsNotSet()
|
||||
{
|
||||
// Arrange & Act
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => Client.GetAsync("http://localhost/CacheHeaders/ThrowsWhenDurationIsNotSet"));
|
||||
Assert.Equal(
|
||||
"If the 'NoStore' property is not set to true, 'Duration' property must be specified.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
// Cache Profiles
|
||||
[Fact]
|
||||
public async Task ResponseCache_SetsAllHeaders_FromCacheProfile()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfiles/PublicCache30Sec");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=30", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCache_SetsAllHeaders_ChosesTheRightProfile()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfiles/PrivateCache30Sec");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("max-age=30, private", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCache_SetsNoCacheHeaders()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfiles/NoCache");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("no-store, no-cache", data);
|
||||
data = Assert.Single(response.Headers.GetValues("Pragma"));
|
||||
Assert.Equal("no-cache", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCache_AddsHeaders()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfiles/CacheProfileAddParameter");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=30", data);
|
||||
data = Assert.Single(response.Headers.GetValues("Vary"));
|
||||
Assert.Equal("Accept", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCache_ModifiesHeaders()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfiles/CacheProfileOverride");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=10", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCache_FallbackToFilter_IfNoAttribute()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfiles/FallbackToFilter");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
Assert.Equal("no-store", data);
|
||||
data = Assert.Single(response.Headers.GetValues("Vary"));
|
||||
Assert.Equal("TestDefault", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCacheAttribute_OnAction_OverridesTheValuesOnClass()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/ClassLevelNoStore/CacheThisActionWithProfileSettings");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Vary"));
|
||||
Assert.Equal("Accept", data);
|
||||
data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=30", data);
|
||||
IEnumerable<string> pragmaValues;
|
||||
response.Headers.TryGetValues("Pragma", out pragmaValues);
|
||||
Assert.Null(pragmaValues);
|
||||
}
|
||||
|
||||
// Cache profile overrides
|
||||
[Fact]
|
||||
public async Task ResponseCacheAttribute_OverridesProfileDuration_FromAttributeProperty()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfileOverrides/PublicCache30SecTo15Sec");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=15", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCacheAttribute_OverridesProfileLocation_FromAttributeProperty()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfileOverrides/PublicCache30SecToPrivateCache");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("max-age=30, private", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCacheAttribute_OverridesProfileNoStore_FromAttributeProperty()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/CacheProfileOverrides/PublicCache30SecToNoStore");
|
||||
|
||||
// Assert
|
||||
var data = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
Assert.Equal("no-store", data);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCacheAttribute_OverridesProfileVaryBy_FromAttributeProperty()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync(
|
||||
"http://localhost/CacheProfileOverrides/PublicCache30SecWithVaryByAcceptToVaryByTest");
|
||||
|
||||
// Assert
|
||||
var cacheControl = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=30", cacheControl);
|
||||
var vary = Assert.Single(response.Headers.GetValues("Vary"));
|
||||
Assert.Equal("Test", vary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseCacheAttribute_OverridesProfileVaryBy_FromAttributeProperty_AndRemovesVaryHeader()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync(
|
||||
"http://localhost/CacheProfileOverrides/PublicCache30SecWithVaryByAcceptToVaryByNone");
|
||||
|
||||
// Assert
|
||||
var cacheControl = Assert.Single(response.Headers.GetValues("Cache-control"));
|
||||
AssertHeaderEquals("public, max-age=30", cacheControl);
|
||||
Assert.Throws<InvalidOperationException>(() => response.Headers.GetValues("Vary"));
|
||||
}
|
||||
|
||||
private void AssertHeaderEquals(string expected, string actual)
|
||||
{
|
||||
// OrderBy is used because the order of the results may very depending on the platform / client.
|
||||
Assert.Equal(
|
||||
expected.Split(',').Select(p => p.Trim()).OrderBy(item => item, StringComparer.Ordinal),
|
||||
actual.Split(',').Select(p => p.Trim()).OrderBy(item => item, StringComparer.Ordinal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||
{
|
||||
public class TryValidateModelTest : IClassFixture<MvcTestFixture<ValidationWebSite.Startup>>
|
||||
{
|
||||
public TryValidateModelTest(MvcTestFixture<ValidationWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task TryValidateModel_ClearParameterValidationError_ReturnsErrorsForInvalidProperties()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Price\": 2, \"Contact\": \"acvrdzersaererererfdsfdsfdsfsdf\", " +
|
||||
"\"ProductDetails\": {\"Detail1\": \"d1\", \"Detail2\": \"d2\", \"Detail3\": \"d3\"}}";
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
var url =
|
||||
"http://localhost/ModelMetadataTypeValidation/" +
|
||||
"TryValidateModelAfterClearingValidationErrorInParameter?theImpossibleString=test";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
|
||||
Assert.Equal(4, json.Count);
|
||||
Assert.Equal("CompanyName cannot be null or empty.", json["CompanyName"]);
|
||||
Assert.Equal("The field Price must be between 20 and 100.", json["Price"]);
|
||||
// Mono issue - https://github.com/aspnet/External/issues/19
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Category field is required."),
|
||||
json["Category"]);
|
||||
AssertErrorEquals(
|
||||
"The field Contact Us must be a string with a maximum length of 20." +
|
||||
"The field Contact Us must match the regular expression " +
|
||||
(TestPlatformHelper.IsMono ? "^[0-9]*$." : "'^[0-9]*$'."),
|
||||
json["Contact"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryValidateModel_InvalidTypeOnDerivedModel_ReturnsErrors()
|
||||
{
|
||||
// Arrange
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/TryValidateModelSoftwareViewModelWithPrefix";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync(url);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
|
||||
Assert.Equal(1, json.Count);
|
||||
Assert.Equal("Product must be made in the USA if it is not named.", json["software"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryValidateModel_ValidDerivedModel_ReturnsEmptyResponseBody()
|
||||
{
|
||||
// Arrange
|
||||
var url = "http://localhost/ModelMetadataTypeValidation/TryValidateModelValidModelNoPrefix";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync(url);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal("{}", body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TryValidateModel_CollectionsModel_ReturnsErrorsForInvalidProperties()
|
||||
{
|
||||
// Arrange
|
||||
var input = "[ { \"Price\": 2, \"Contact\": \"acvrdzersaererererfdsfdsfdsfsdf\", " +
|
||||
"\"ProductDetails\": {\"Detail1\": \"d1\", \"Detail2\": \"d2\", \"Detail3\": \"d3\"} }," +
|
||||
"{\"Price\": 2, \"Contact\": \"acvrdzersaererererfdsfdsfdsfsdf\", " +
|
||||
"\"ProductDetails\": {\"Detail1\": \"d1\", \"Detail2\": \"d2\", \"Detail3\": \"d3\"} }]";
|
||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
||||
var url =
|
||||
"http://localhost/ModelMetadataTypeValidation/TryValidateModelWithCollectionsModel";
|
||||
|
||||
// Act
|
||||
var response = await Client.PostAsync(url, content);
|
||||
|
||||
// Assert
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(body);
|
||||
Assert.Equal("CompanyName cannot be null or empty.", json["[0].CompanyName"]);
|
||||
Assert.Equal("The field Price must be between 20 and 100.", json["[0].Price"]);
|
||||
// Mono issue - https://github.com/aspnet/External/issues/19
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Category field is required."),
|
||||
json["[0].Category"]);
|
||||
AssertErrorEquals(
|
||||
"The field Contact Us must be a string with a maximum length of 20." +
|
||||
"The field Contact Us must match the regular expression " +
|
||||
(TestPlatformHelper.IsMono ? "^[0-9]*$." : "'^[0-9]*$'."),
|
||||
json["[0].Contact"]);
|
||||
Assert.Equal("CompanyName cannot be null or empty.", json["[1].CompanyName"]);
|
||||
Assert.Equal("The field Price must be between 20 and 100.", json["[1].Price"]);
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Category field is required."),
|
||||
json["[1].Category"]);
|
||||
AssertErrorEquals(
|
||||
"The field Contact Us must be a string with a maximum length of 20." +
|
||||
"The field Contact Us must match the regular expression " +
|
||||
(TestPlatformHelper.IsMono ? "^[0-9]*$." : "'^[0-9]*$'."),
|
||||
json["[1].Contact"]);
|
||||
}
|
||||
|
||||
private void AssertErrorEquals(string expected, string actual)
|
||||
{
|
||||
// OrderBy is used because the order of the results may very depending on the platform / client.
|
||||
Assert.Equal(
|
||||
expected.Split('.').OrderBy(item => item, StringComparer.Ordinal),
|
||||
actual.Split('.').OrderBy(item => item, StringComparer.Ordinal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Create in Aria area. - My ASP.NET Application</title>
|
||||
<title>Create in Area1 area. - My ASP.NET Application</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<a href="/">Validation web site</a>
|
||||
<a href="/RemoteAttribute_Home/Details">Basic web site</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/Aria">Aria Home</a></li>
|
||||
<li><a href="/RemoteAttribute_Home/Details">Home</a></li>
|
||||
<li><a href="/Area1/RemoteAttribute_Home/Details">Area1 Home</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
<div>
|
||||
|
||||
<h2>Create in Aria area.</h2>
|
||||
<form action="/Aria/RemoteAttribute_Home/Create" method="post"> <div class="form-horizontal">
|
||||
<h2>Create in Area1 area.</h2>
|
||||
<form action="/Area1/RemoteAttribute_Home/Create" method="post"> <div class="form-horizontal">
|
||||
<h4>Person</h4>
|
||||
<hr />
|
||||
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label col-md-2" for="UserId1">UserId1</label>
|
||||
<div class="col-md-10">
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="'UserId1' is invalid." data-val-remote-additionalfields="*.UserId1" data-val-remote-url="/Aria/RemoteAttribute_Verify/IsIdAvailable" id="UserId1" name="UserId1" type="text" value="" />
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="'UserId1' is invalid." data-val-remote-additionalfields="*.UserId1" data-val-remote-url="/Area1/RemoteAttribute_Verify/IsIdAvailable" id="UserId1" name="UserId1" type="text" value="" />
|
||||
<span class="field-validation-valid text-danger" data-valmsg-for="UserId1" data-valmsg-replace="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label col-md-2" for="UserId3">UserId3</label>
|
||||
<div class="col-md-10">
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="/Aria/RemoteAttribute_Verify/IsIdAvailable rejects you." data-val-remote-additionalfields="*.UserId3" data-val-remote-url="/Aria/RemoteAttribute_Verify/IsIdAvailable" id="UserId3" name="UserId3" type="text" value="" />
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="/Area1/RemoteAttribute_Verify/IsIdAvailable rejects you." data-val-remote-additionalfields="*.UserId3" data-val-remote-url="/Area1/RemoteAttribute_Verify/IsIdAvailable" id="UserId3" name="UserId3" type="text" value="" />
|
||||
<span class="field-validation-valid text-danger" data-valmsg-for="UserId3" data-valmsg-replace="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label col-md-2" for="UserId4">UserId4</label>
|
||||
<div class="col-md-10">
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="'UserId4' is invalid." data-val-remote-additionalfields="*.UserId4,*.UserId1,*.UserId2,*.UserId3" data-val-remote-url="/AnotherAria/RemoteAttribute_Verify/IsIdAvailable" id="UserId4" name="UserId4" type="text" value="" />
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="'UserId4' is invalid." data-val-remote-additionalfields="*.UserId4,*.UserId1,*.UserId2,*.UserId3" data-val-remote-url="/Area2/RemoteAttribute_Verify/IsIdAvailable" id="UserId4" name="UserId4" type="text" value="" />
|
||||
<span class="field-validation-valid text-danger" data-valmsg-for="UserId4" data-valmsg-replace="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
</div>
|
||||
</form>
|
||||
<div>
|
||||
<a href="/Aria">Go back to home</a>
|
||||
<a href="/Area1/RemoteAttribute_Home/Details">Go back to home</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
|
@ -9,13 +9,13 @@
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<a href="/">Validation web site</a>
|
||||
<a href="/RemoteAttribute_Home/Details">Basic web site</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/Aria">Aria Home</a></li>
|
||||
<li><a href="/RemoteAttribute_Home/Details">Home</a></li>
|
||||
<li><a href="/Area1/RemoteAttribute_Home/Details">Area1 Home</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label col-md-2" for="UserId3">UserId3</label>
|
||||
<div class="col-md-10">
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="/Aria/RemoteAttribute_Verify/IsIdAvailable rejects you." data-val-remote-additionalfields="*.UserId3" data-val-remote-url="/Aria/RemoteAttribute_Verify/IsIdAvailable" id="UserId3" name="UserId3" type="text" value="" />
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="/Area1/RemoteAttribute_Verify/IsIdAvailable rejects you." data-val-remote-additionalfields="*.UserId3" data-val-remote-url="/Area1/RemoteAttribute_Verify/IsIdAvailable" id="UserId3" name="UserId3" type="text" value="" />
|
||||
<span class="field-validation-valid text-danger" data-valmsg-for="UserId3" data-valmsg-replace="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label col-md-2" for="UserId4">UserId4</label>
|
||||
<div class="col-md-10">
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="'UserId4' is invalid." data-val-remote-additionalfields="*.UserId4,*.UserId1,*.UserId2,*.UserId3" data-val-remote-url="/AnotherAria/RemoteAttribute_Verify/IsIdAvailable" id="UserId4" name="UserId4" type="text" value="" />
|
||||
<input class="form-control text-box single-line" data-val="true" data-val-remote="'UserId4' is invalid." data-val-remote-additionalfields="*.UserId4,*.UserId1,*.UserId2,*.UserId3" data-val-remote-url="/Area2/RemoteAttribute_Verify/IsIdAvailable" id="UserId4" name="UserId4" type="text" value="" />
|
||||
<span class="field-validation-valid text-danger" data-valmsg-for="UserId4" data-valmsg-replace="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
</div>
|
||||
</form>
|
||||
<div>
|
||||
<a href="/">Go back to home</a>
|
||||
<a href="/RemoteAttribute_Home/Details">Go back to home</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
@ -49,12 +49,10 @@
|
|||
"RazorEmbeddedViewsWebSite": "1.0.0",
|
||||
"RazorPageExecutionInstrumentationWebSite": "1.0.0",
|
||||
"RazorWebSite": "1.0.0",
|
||||
"ResponseCacheWebSite": "1.0.0",
|
||||
"RoutingWebSite": "1.0.0",
|
||||
"TagHelperSample.Web": "1.0.0",
|
||||
"TagHelpersWebSite": "1.0.0",
|
||||
"UrlHelperWebSite": "1.0.0",
|
||||
"ValidationWebSite": "1.0.0",
|
||||
"UrlHelperSample.Web": "1.0.0",
|
||||
"VersioningWebSite": "1.0.0",
|
||||
"WebApiCompatShimWebSite": "1.0.0",
|
||||
"XmlFormattersWebSite": "1.0.0",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
@ -25,6 +26,287 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public string Street { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_ValidBaseClass_NoModelStateErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Name\": \"MVC\", \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 21, " +
|
||||
"\"ProductDetails\": {\"Detail1\": \"d1\", \"Detail2\": \"d2\", \"Detail3\": \"d3\"}}";
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
ParameterType = typeof(ProductViewModel),
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BindingSource = BindingSource.Body
|
||||
}
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json;charset=utf-8";
|
||||
});
|
||||
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<ProductViewModel>(modelBindingResult.Model);
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.NotNull(boundPerson);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidPropertiesAndSubPropertiesOnBaseClass_HasModelStateErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Price\": 2, \"ProductDetails\": {\"Detail1\": \"d1\"}}";
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BindingSource = BindingSource.Body
|
||||
},
|
||||
ParameterType = typeof(ProductViewModel)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json";
|
||||
});
|
||||
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<ProductViewModel>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.False(modelState.IsValid);
|
||||
var modelStateErrors = CreateValidationDictionary(modelState);
|
||||
Assert.Equal("CompanyName cannot be null or empty.", modelStateErrors["CompanyName"]);
|
||||
Assert.Equal("The field Price must be between 20 and 100.", modelStateErrors["Price"]);
|
||||
// Mono issue - https://github.com/aspnet/External/issues/19
|
||||
Assert.Equal(PlatformNormalizer.NormalizeContent("The Category field is required."), modelStateErrors["Category"]);
|
||||
Assert.Equal(PlatformNormalizer.NormalizeContent("The Contact Us field is required."), modelStateErrors["Contact"]);
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Detail2 field is required."),
|
||||
modelStateErrors["ProductDetails.Detail2"]);
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Detail3 field is required."),
|
||||
modelStateErrors["ProductDetails.Detail3"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidComplexTypePropertyOnBaseClass_HasModelStateErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Contact\":\"4255678765\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 21 }";
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BindingSource = BindingSource.Body
|
||||
},
|
||||
ParameterType = typeof(ProductViewModel)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json";
|
||||
});
|
||||
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<ProductViewModel>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.False(modelState.IsValid);
|
||||
var modelStateErrors = CreateValidationDictionary(modelState);
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The ProductDetails field is required."),
|
||||
modelStateErrors["ProductDetails"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidClassAttributeOnBaseClass_HasModelStateErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"UK\",\"Price\": 21, \"ProductDetails\": {\"Detail1\": \"d1\"," +
|
||||
" \"Detail2\": \"d2\", \"Detail3\": \"d3\"}}";
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BindingSource = BindingSource.Body
|
||||
},
|
||||
ParameterType = typeof(ProductViewModel)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json";
|
||||
});
|
||||
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<ProductViewModel>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.False(modelState.IsValid);
|
||||
var modelStateErrors = CreateValidationDictionary(modelState);
|
||||
Assert.Single(modelStateErrors);
|
||||
Assert.Equal("Product must be made in the USA if it is not named.", modelStateErrors[""]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_ValidDerivedClass_NoModelStateErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Name\": \"MVC\", \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\", \"Version\":\"2\"," +
|
||||
"\"DatePurchased\": \"/Date(1297246301973)/\", \"Price\" : \"110\" }";
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BindingSource = BindingSource.Body
|
||||
},
|
||||
ParameterType = typeof(SoftwareViewModel)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json";
|
||||
});
|
||||
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<SoftwareViewModel>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.True(modelState.IsValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidPropertiesOnDerivedClass_HasModelStateErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Name\": \"MVC\", \"Contact\":\"425-895-9019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"USA\",\"Price\": 2}";
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BindingSource = BindingSource.Body
|
||||
},
|
||||
ParameterType = typeof(SoftwareViewModel)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json";
|
||||
});
|
||||
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<SoftwareViewModel>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.False(modelState.IsValid);
|
||||
var modelStateErrors = CreateValidationDictionary(modelState);
|
||||
Assert.Equal(2, modelStateErrors.Count);
|
||||
Assert.Equal("The field Price must be between 100 and 200.", modelStateErrors["Price"]);
|
||||
Assert.Equal("The field Contact must be a string with a maximum length of 10.", modelStateErrors["Contact"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelMetaDataTypeAttribute_InvalidClassAttributeOnBaseClassProduct_HasModelStateErrors()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{ \"Contact\":\"4258959019\", \"Category\":\"Technology\"," +
|
||||
"\"CompanyName\":\"Microsoft\", \"Country\":\"UK\",\"Version\":\"2\"," +
|
||||
"\"DatePurchased\": \"/Date(1297246301973)/\", \"Price\" : \"110\" }";
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BindingSource = BindingSource.Body
|
||||
},
|
||||
ParameterType = typeof(SoftwareViewModel)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json";
|
||||
});
|
||||
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<SoftwareViewModel>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.False(modelState.IsValid);
|
||||
var modelStateErrors = CreateValidationDictionary(modelState);
|
||||
Assert.Single(modelStateErrors);
|
||||
Assert.Equal("Product must be made in the USA if it is not named.", modelStateErrors[""]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FromBodyAndRequiredOnProperty_EmptyBody_AddsModelStateError()
|
||||
{
|
||||
|
|
@ -376,5 +658,27 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
var entry = Assert.Single(modelState);
|
||||
Assert.Equal("CustomParameter.Address", entry.Key);
|
||||
}
|
||||
|
||||
private Dictionary<string, string> CreateValidationDictionary(ModelStateDictionary modelState)
|
||||
{
|
||||
var result = new Dictionary<string, string>();
|
||||
foreach (var item in modelState)
|
||||
{
|
||||
var errorMessage = string.Empty;
|
||||
foreach (var error in item.Value.Errors)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
errorMessage = errorMessage + error.ErrorMessage;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(errorMessage))
|
||||
{
|
||||
result.Add(item.Key, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace ValidationWebSite
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
public class CompanyNameAttribute : ValidationAttribute
|
||||
{
|
||||
|
|
@ -18,4 +18,4 @@ namespace ValidationWebSite
|
|||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace ValidationWebSite.Models
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
[ProductValidator]
|
||||
public class Product
|
||||
|
|
@ -27,4 +26,4 @@ namespace ValidationWebSite.Models
|
|||
[Required]
|
||||
public ProductDetails ProductDetails { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace ValidationWebSite.Models
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
public class ProductDetails
|
||||
{
|
||||
|
|
@ -16,4 +16,4 @@ namespace ValidationWebSite.Models
|
|||
[Required]
|
||||
public string Detail3 { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using ValidationWebSite.Models;
|
||||
|
||||
namespace ValidationWebSite.ViewModels
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
[ModelMetadataType(typeof(Product))]
|
||||
public class ProductViewModel
|
||||
|
|
@ -29,4 +26,4 @@ namespace ValidationWebSite.ViewModels
|
|||
|
||||
public ProductDetails ProductDetails { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace ValidationWebSite.Models
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
public class Software : Product
|
||||
{
|
||||
|
|
@ -19,4 +19,4 @@ namespace ValidationWebSite.Models
|
|||
[StringLength(10)]
|
||||
public new string Contact { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,13 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using ValidationWebSite.Models;
|
||||
|
||||
namespace ValidationWebSite.ViewModels
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
[ModelMetadataType(typeof(Software))]
|
||||
public class SoftwareViewModel
|
||||
public class SoftwareViewModel
|
||||
{
|
||||
[RegularExpression("^[0-9]*$")]
|
||||
public string Version { get; set; }
|
||||
|
|
@ -28,4 +26,4 @@ namespace ValidationWebSite.ViewModels
|
|||
|
||||
public string CompanyName { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using ValidationWebSite.ViewModels;
|
||||
|
||||
namespace ValidationWebSite
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
public class ProductValidatorAttribute : ValidationAttribute
|
||||
{
|
||||
|
|
@ -39,4 +38,4 @@ namespace ValidationWebSite
|
|||
+ value.GetType() + " instance");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
// 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.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
public class TryValidateModelIntegrationTest
|
||||
{
|
||||
[Fact]
|
||||
public void ModelState_IsInvalid_ForInvalidData_OnDerivedModel()
|
||||
{
|
||||
// Arrange
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext();
|
||||
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
var model = new SoftwareViewModel
|
||||
{
|
||||
Category = "Technology",
|
||||
CompanyName = "Microsoft",
|
||||
Contact = "4258393231",
|
||||
Country = "UK", // Here the validate country is USA only
|
||||
DatePurchased = new DateTime(2010, 10, 10),
|
||||
Price = 110,
|
||||
Version = "2"
|
||||
};
|
||||
var oldModel = model;
|
||||
|
||||
// Act
|
||||
var result = TryValidateModel(model, "software", operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
Assert.Same(oldModel, model);
|
||||
Assert.False(modelState.IsValid);
|
||||
var modelStateErrors = GetModelStateErrors(modelState);
|
||||
Assert.Single(modelStateErrors);
|
||||
Assert.Equal("Product must be made in the USA if it is not named.", modelStateErrors["software"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ModelState_IsValid_ForValidData_OnDerivedModel()
|
||||
{
|
||||
// Arrange
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext();
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
var model = new SoftwareViewModel
|
||||
{
|
||||
Category = "Technology",
|
||||
CompanyName = "Microsoft",
|
||||
Contact = "4258393231",
|
||||
Country = "USA",
|
||||
DatePurchased = new DateTime(2010, 10, 10),
|
||||
Name = "MVC",
|
||||
Price = 110,
|
||||
Version = "2"
|
||||
};
|
||||
var oldModel = model;
|
||||
|
||||
// Act
|
||||
var result = TryValidateModel(model, prefix: string.Empty, operationContext: operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
Assert.Same(oldModel, model);
|
||||
Assert.True(modelState.IsValid);
|
||||
var modelStateErrors = GetModelStateErrors(modelState);
|
||||
Assert.Empty(modelStateErrors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryValidateModel_CollectionsModel_ReturnsErrorsForInvalidProperties()
|
||||
{
|
||||
// Arrange
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext();
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
var model = new List<ProductViewModel>();
|
||||
model.Add(new ProductViewModel()
|
||||
{
|
||||
Price = 2,
|
||||
Contact = "acvrdzersaererererfdsfdsfdsfsdf",
|
||||
ProductDetails = new ProductDetails()
|
||||
{
|
||||
Detail1 = "d1",
|
||||
Detail2 = "d2",
|
||||
Detail3 = "d3"
|
||||
}
|
||||
});
|
||||
model.Add(new ProductViewModel()
|
||||
{
|
||||
Price = 2,
|
||||
Contact = "acvrdzersaererererfdsfdsfdsfsdf",
|
||||
ProductDetails = new ProductDetails()
|
||||
{
|
||||
Detail1 = "d1",
|
||||
Detail2 = "d2",
|
||||
Detail3 = "d3"
|
||||
}
|
||||
});
|
||||
var oldModel = model;
|
||||
|
||||
// Act
|
||||
var result = TryValidateModel(model, prefix: string.Empty, operationContext: operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
Assert.False(modelState.IsValid);
|
||||
var modelStateErrors = GetModelStateErrors(modelState);
|
||||
Assert.Equal("CompanyName cannot be null or empty.", modelStateErrors["[0].CompanyName"]);
|
||||
Assert.Equal("The field Price must be between 20 and 100.", modelStateErrors["[0].Price"]);
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Category field is required."),
|
||||
modelStateErrors["[0].Category"]);
|
||||
AssertErrorEquals(
|
||||
"The field Contact Us must be a string with a maximum length of 20." +
|
||||
"The field Contact Us must match the regular expression " +
|
||||
(TestPlatformHelper.IsMono ? "^[0-9]*$." : "'^[0-9]*$'."),
|
||||
modelStateErrors["[0].Contact"]);
|
||||
Assert.Equal("CompanyName cannot be null or empty.", modelStateErrors["[1].CompanyName"]);
|
||||
Assert.Equal("The field Price must be between 20 and 100.", modelStateErrors["[1].Price"]);
|
||||
Assert.Equal(
|
||||
PlatformNormalizer.NormalizeContent("The Category field is required."),
|
||||
modelStateErrors["[1].Category"]);
|
||||
AssertErrorEquals(
|
||||
"The field Contact Us must be a string with a maximum length of 20." +
|
||||
"The field Contact Us must match the regular expression " +
|
||||
(TestPlatformHelper.IsMono ? "^[0-9]*$." : "'^[0-9]*$'."),
|
||||
modelStateErrors["[1].Contact"]);
|
||||
}
|
||||
|
||||
private bool TryValidateModel(
|
||||
object model,
|
||||
string prefix,
|
||||
OperationBindingContext operationContext)
|
||||
{
|
||||
var controller = new TestController();
|
||||
controller.ControllerContext = new ControllerContext(operationContext.ActionContext);
|
||||
controller.ObjectValidator = ModelBindingTestHelper.GetObjectValidator(operationContext.MetadataProvider);
|
||||
controller.MetadataProvider = operationContext.MetadataProvider;
|
||||
controller.ControllerContext.ValidatorProviders = new[] { operationContext.ValidatorProvider }.ToList();
|
||||
|
||||
return controller.TryValidateModel(model, prefix);
|
||||
}
|
||||
|
||||
private void AssertErrorEquals(string expected, string actual)
|
||||
{
|
||||
// OrderBy is used because the order of the results may very depending on the platform / client.
|
||||
Assert.Equal(
|
||||
expected.Split('.').OrderBy(item => item, StringComparer.Ordinal),
|
||||
actual.Split('.').OrderBy(item => item, StringComparer.Ordinal));
|
||||
}
|
||||
|
||||
private Dictionary<string, string> GetModelStateErrors(ModelStateDictionary modelState)
|
||||
{
|
||||
var result = new Dictionary<string, string>();
|
||||
foreach (var item in modelState)
|
||||
{
|
||||
var errorMessage = string.Empty;
|
||||
foreach (var error in item.Value.Errors)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
errorMessage = errorMessage + error.ErrorMessage;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(errorMessage))
|
||||
{
|
||||
result.Add(item.Key, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private class TestController : Controller
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +1,39 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using BasicWebSite.Models;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using ValidationWebSite.Models;
|
||||
|
||||
namespace ValidationWebSite.Controllers
|
||||
namespace BasicWebSite.Areas.Area1.Controllers
|
||||
{
|
||||
[Area("Area1")]
|
||||
[Route("[area]/[controller]/[action]")]
|
||||
public class RemoteAttribute_HomeController : Controller
|
||||
{
|
||||
private static Person _person;
|
||||
private static RemoteAttributeUser _user;
|
||||
|
||||
[HttpGet]
|
||||
[Route("[Controller]/[Action]")]
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("[Controller]/[Action]")]
|
||||
public IActionResult Create(Person person)
|
||||
public IActionResult Create(RemoteAttributeUser user)
|
||||
{
|
||||
ModelState.Remove("id");
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(person);
|
||||
return View(user);
|
||||
}
|
||||
|
||||
_person = person;
|
||||
_user = user;
|
||||
return RedirectToAction(nameof(Details));
|
||||
}
|
||||
|
||||
[Route("", Name = "Home", Order = -1)]
|
||||
[Route("[Controller]/Index")]
|
||||
public IActionResult Details()
|
||||
{
|
||||
return View(_person);
|
||||
return View(_user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,15 +3,15 @@
|
|||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ValidationWebSite.MyArea.Controllers
|
||||
namespace BasicWebSite.Areas.Area1.Controllers
|
||||
{
|
||||
[Area("Aria")]
|
||||
[Area("Area1")]
|
||||
[Route("[area]/[controller]/[action]")]
|
||||
public class RemoteAttribute_VerifyController : Controller
|
||||
{
|
||||
// This action is overloaded and may receive requests to validate either UserId1 or UserId3.
|
||||
// Demonstrates use of the default error message.
|
||||
[AcceptVerbs("Get", "Post")]
|
||||
[Route("[Area]/[Controller]/[Action]", Order = -2)]
|
||||
public IActionResult IsIdAvailable(string userId1, string userId3)
|
||||
{
|
||||
return Json(data: false);
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
@model ValidationWebSite.Models.Person
|
||||
@model BasicWebSite.Models.RemoteAttributeUser
|
||||
@{
|
||||
Layout = "_Layout.cshtml";
|
||||
object areaObject;
|
||||
ViewContext.ActionDescriptor.RouteValueDefaults.TryGetValue("area", out areaObject);
|
||||
var areaName = (areaObject as string) ?? "root";
|
||||
|
||||
ViewBag.Title = "Create in " + areaName + " area.";
|
||||
}
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
@model ValidationWebSite.Models.Person
|
||||
@model BasicWebSite.Models.RemoteAttributeUser
|
||||
@{
|
||||
Layout = "_Layout.cshtml";
|
||||
object areaObject;
|
||||
ViewContext.ActionDescriptor.RouteValueDefaults.TryGetValue("area", out areaObject);
|
||||
var areaName = (areaObject as string) ?? "root";
|
||||
|
||||
ViewBag.Title = "Details in " + areaName + " area.";
|
||||
}
|
||||
|
||||
|
|
@ -64,13 +64,5 @@
|
|||
</div>
|
||||
|
||||
<p>
|
||||
@Html.ActionLink("Create a new one", "Create") |
|
||||
@if (string.Equals("Aria", areaName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@Html.RouteLink("Go back to home", "Home")
|
||||
}
|
||||
else
|
||||
{
|
||||
@Html.RouteLink("Go to Aria home", "AriaHome")
|
||||
}
|
||||
@Html.ActionLink("Create a new one", "Create")
|
||||
</p>
|
||||
|
|
@ -9,13 +9,13 @@
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
@Html.ActionLink("Validation web site", "Details", "RemoteAttribute_Home", routeValues: new { area = (object)null })
|
||||
@Html.ActionLink("Basic web site", "Details", "RemoteAttribute_Home", routeValues: new { area = (object)null })
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul>
|
||||
<li>@Html.ActionLink("Home", "Details", "RemoteAttribute_Home", routeValues: new { area = string.Empty })</li>
|
||||
<li>@Html.ActionLink("Aria Home", "Details", "RemoteAttribute_Home", routeValues: new { area = "Aria" })</li>
|
||||
<li>@Html.ActionLink("Area1 Home", "Details", "RemoteAttribute_Home", routeValues: new { area = "Area1" })</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -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.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using BasicWebSite.Models;
|
||||
|
||||
namespace BasicWebSite.Ares.Area2.Controllers
|
||||
{
|
||||
[Area("Area2")]
|
||||
[Route("[area]/[controller]/[action]")]
|
||||
public class RemoteAttribute_VerifyController : Controller
|
||||
{
|
||||
// Demonstrates validation action when AdditionalFields causes client to send multiple values.
|
||||
[HttpGet]
|
||||
public IActionResult IsIdAvailable(RemoteAttributeUser user)
|
||||
{
|
||||
return Json(data: string.Format(
|
||||
"/Area2/RemoteAttribute_Verify/IsIdAvailable rejects '{0}' with '{1}', '{2}', and '{3}'.",
|
||||
user.UserId4,
|
||||
user.UserId1,
|
||||
user.UserId2,
|
||||
user.UserId3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using BasicWebSite.Models;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using ValidationWebSite.Models;
|
||||
|
||||
namespace ValidationWebSite.MyArea.Controllers
|
||||
namespace BasicWebSite.Controllers
|
||||
{
|
||||
[Area("Aria")]
|
||||
[Route("[Area]/[Controller]/[Action]", Order = -2)]
|
||||
[Route("[controller]/[action]")]
|
||||
public class RemoteAttribute_HomeController : Controller
|
||||
{
|
||||
private static Person _person;
|
||||
private static RemoteAttributeUser _user;
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Create()
|
||||
|
|
@ -19,23 +18,21 @@ namespace ValidationWebSite.MyArea.Controllers
|
|||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(Person person)
|
||||
public IActionResult Create(RemoteAttributeUser user)
|
||||
{
|
||||
ModelState.Remove("id");
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(person);
|
||||
return View(user);
|
||||
}
|
||||
|
||||
_person = person;
|
||||
_user = user;
|
||||
return RedirectToAction(nameof(Details));
|
||||
}
|
||||
|
||||
[Route("/[Area]", Name = "AriaHome", Order = -3)]
|
||||
[Route("/[Area]/[Controller]/Index", Order = -2)]
|
||||
public IActionResult Details()
|
||||
{
|
||||
return View(_person);
|
||||
return View(_user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ValidationWebSite.Controllers
|
||||
namespace BasicWebSite.Controllers
|
||||
{
|
||||
[Route("[Controller]/[Action]")]
|
||||
[Route("[controller]/[action]")]
|
||||
public class RemoteAttribute_VerifyController : Controller
|
||||
{
|
||||
// This action is overloaded and may receive requests to validate either UserId1 or UserId2.
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// 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.AspNet.Mvc;
|
||||
|
||||
namespace BasicWebSite.Models
|
||||
{
|
||||
public class RemoteAttributeUser
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
// Controller in current area.
|
||||
[Remote(action: "IsIdAvailable", controller: "RemoteAttribute_Verify")]
|
||||
public string UserId1 { get; set; }
|
||||
|
||||
// Controller in root area.
|
||||
[Remote(action: "IsIdAvailable", controller: "RemoteAttribute_Verify", areaName: null, HttpMethod = "Post")]
|
||||
public string UserId2 { get; set; }
|
||||
|
||||
[Remote(
|
||||
action: "IsIdAvailable",
|
||||
controller: "RemoteAttribute_Verify",
|
||||
areaName:"Area1",
|
||||
ErrorMessage = "/Area1/RemoteAttribute_Verify/IsIdAvailable rejects you.")]
|
||||
public string UserId3 { get; set; }
|
||||
|
||||
[Remote(
|
||||
action:"IsIdAvailable",
|
||||
controller: "RemoteAttribute_Verify",
|
||||
areaName: "Area2",
|
||||
AdditionalFields = "UserId1, UserId2, UserId3")]
|
||||
public string UserId4 { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,8 @@ namespace BasicWebSite
|
|||
{
|
||||
app.UseCultureReplacer();
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
// Initializes the RequestId service for each request
|
||||
app.UseMiddleware<RequestIdMiddleware>();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
@model BasicWebSite.Models.RemoteAttributeUser
|
||||
@{
|
||||
Layout = "_Layout.cshtml";
|
||||
object areaObject;
|
||||
ViewContext.ActionDescriptor.RouteValueDefaults.TryGetValue("area", out areaObject);
|
||||
var areaName = (areaObject as string) ?? "root";
|
||||
ViewBag.Title = "Create in " + areaName + " area.";
|
||||
}
|
||||
|
||||
<h2>@ViewBag.Title</h2>
|
||||
@using (Html.BeginForm())
|
||||
{
|
||||
<div class="form-horizontal">
|
||||
<h4>Person</h4>
|
||||
<hr />
|
||||
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
|
||||
|
||||
<div class="form-group">
|
||||
@Html.LabelFor(model => model.Id, htmlAttributes: new { @class = "control-label col-md-2" })
|
||||
<div class="col-md-10">
|
||||
@Html.EditorFor(model => model.Id, new { htmlAttributes = new { @class = "form-control" } })
|
||||
@Html.ValidationMessageFor(model => model.Id, "", new { @class = "text-danger" })
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@Html.LabelFor(model => model.UserId1, htmlAttributes: new { @class = "control-label col-md-2" })
|
||||
<div class="col-md-10">
|
||||
@Html.EditorFor(model => model.UserId1, new { htmlAttributes = new { @class = "form-control" } })
|
||||
@Html.ValidationMessageFor(model => model.UserId1, "", new { @class = "text-danger" })
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@Html.LabelFor(model => model.UserId2, htmlAttributes: new { @class = "control-label col-md-2" })
|
||||
<div class="col-md-10">
|
||||
@Html.EditorFor(model => model.UserId2, new { htmlAttributes = new { @class = "form-control" } })
|
||||
@Html.ValidationMessageFor(model => model.UserId2, "", new { @class = "text-danger" })
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@Html.LabelFor(model => model.UserId3, htmlAttributes: new { @class = "control-label col-md-2" })
|
||||
<div class="col-md-10">
|
||||
@Html.EditorFor(model => model.UserId3, new { htmlAttributes = new { @class = "form-control" } })
|
||||
@Html.ValidationMessageFor(model => model.UserId3, "", new { @class = "text-danger" })
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@Html.LabelFor(model => model.UserId4, htmlAttributes: new { @class = "control-label col-md-2" })
|
||||
<div class="col-md-10">
|
||||
@Html.EditorFor(model => model.UserId4, new { htmlAttributes = new { @class = "form-control" } })
|
||||
@Html.ValidationMessageFor(model => model.UserId4, "", new { @class = "text-danger" })
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-2 col-md-10">
|
||||
<input type="submit" value="Create" class="btn btn-default" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div>
|
||||
@Html.ActionLink("Go back to home", "Details")
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@* Until script helpers are available, add script references manually. *@
|
||||
@* @Scripts.Render("~/bundles/jqueryval") *@
|
||||
<script src="@Url.Content("~/lib/jquery-validation/jquery.validate.js")"></script>
|
||||
<script src="@Url.Content("~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js")"></script>
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
@model BasicWebSite.Models.RemoteAttributeUser
|
||||
@{
|
||||
Layout = "_Layout.cshtml";
|
||||
object areaObject;
|
||||
ViewContext.ActionDescriptor.RouteValueDefaults.TryGetValue("area", out areaObject);
|
||||
var areaName = (areaObject as string) ?? "root";
|
||||
ViewBag.Title = "Details in " + areaName + " area.";
|
||||
}
|
||||
|
||||
<h2>@ViewBag.Title</h2>
|
||||
<div>
|
||||
<h4>Person</h4>
|
||||
<hr />
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>
|
||||
@Html.DisplayNameFor(model => model.Id)
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
@Html.DisplayFor(model => model.Id)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>
|
||||
@Html.DisplayNameFor(model => model.UserId1)
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
@Html.DisplayFor(model => model.UserId1)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>
|
||||
@Html.DisplayNameFor(model => model.UserId2)
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
@Html.DisplayFor(model => model.UserId2)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>
|
||||
@Html.DisplayNameFor(model => model.UserId3)
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
@Html.DisplayFor(model => model.UserId3)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>
|
||||
@Html.DisplayNameFor(model => model.UserId4)
|
||||
</dt>
|
||||
|
||||
<dd>
|
||||
@Html.DisplayFor(model => model.UserId4)
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
@Html.ActionLink("Create a new one", "Create")
|
||||
</p>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>@ViewBag.Title - My ASP.NET Application</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
@Html.ActionLink("Basic web site", "Details", "RemoteAttribute_Home", routeValues: new { area = (object)null })
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul>
|
||||
<li>@Html.ActionLink("Home", "Details", "RemoteAttribute_Home", routeValues: new { area = string.Empty })</li>
|
||||
<li>@Html.ActionLink("Area1 Home", "Details", "RemoteAttribute_Home", routeValues: new { area = "Area1" })</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@RenderBody()
|
||||
</div>
|
||||
|
||||
<script src="~/lib/jquery/jquery.js"></script>
|
||||
@RenderSection("scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "ValidationWebSite",
|
||||
"name": "BasicWebSite",
|
||||
"description": "Web site demonstrating various validations.",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
{
|
||||
"version": "0.0.0",
|
||||
"name": "ValidationWebSite",
|
||||
"name": "BasicWebSite",
|
||||
"description": "Web site demonstrating various validations.",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
|
||||
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
|
||||
"weblistener": "Microsoft.AspNet.Server.WebListener",
|
||||
"web": "Microsoft.AspNet.Server.Kestrel"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
||||
|
|
@ -15,5 +15,9 @@
|
|||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
},
|
||||
"webroot": "wwwroot"
|
||||
"exclude": [
|
||||
"wwwroot",
|
||||
"node_modules",
|
||||
"bower_components"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" forwardWindowsAuthToken="false" startupTimeLimit="3600" />
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ResponseCacheWebSite
|
||||
{
|
||||
public class CacheHeadersController : Controller
|
||||
{
|
||||
[HttpGet("/CacheHeaders/Index")]
|
||||
[ResponseCache(Duration = 100, Location = ResponseCacheLocation.Any, VaryByHeader = "Accept")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return Content("Hello World!");
|
||||
}
|
||||
|
||||
[HttpGet("/CacheHeaders/PublicCache")]
|
||||
[ResponseCache(Duration = 100, Location = ResponseCacheLocation.Any)]
|
||||
public IActionResult PublicCache()
|
||||
{
|
||||
return Content("Hello World!");
|
||||
}
|
||||
|
||||
[HttpGet("/CacheHeaders/ClientCache")]
|
||||
[ResponseCache(Duration = 100, Location = ResponseCacheLocation.Client)]
|
||||
public IActionResult ClientCache()
|
||||
{
|
||||
return Content("Hello World!");
|
||||
}
|
||||
|
||||
[HttpGet("/CacheHeaders/NoStore")]
|
||||
[ResponseCache(NoStore = true, Duration = 0)]
|
||||
public IActionResult NoStore()
|
||||
{
|
||||
return Content("Hello World!");
|
||||
}
|
||||
|
||||
[HttpGet("/CacheHeaders/NoCacheAtAll")]
|
||||
[ResponseCache(NoStore = true, Duration = 0, Location = ResponseCacheLocation.None)]
|
||||
public IActionResult NoCacheAtAll()
|
||||
{
|
||||
return Content("Hello World!");
|
||||
}
|
||||
|
||||
[HttpGet("/CacheHeaders/SetHeadersInAction")]
|
||||
[ResponseCache(Duration = 40)]
|
||||
public IActionResult SetHeadersInAction()
|
||||
{
|
||||
Response.Headers["Cache-control"] = "max-age=10";
|
||||
return Content("Hello World!");
|
||||
}
|
||||
|
||||
[HttpGet("/CacheHeaders/SetsCacheControlPublicByDefault")]
|
||||
[ResponseCache(Duration = 40)]
|
||||
public IActionResult SetsCacheControlPublicByDefault()
|
||||
{
|
||||
return Content("Hello World!");
|
||||
}
|
||||
|
||||
[HttpGet("/CacheHeaders/ThrowsWhenDurationIsNotSet")]
|
||||
[ResponseCache(VaryByHeader = "Accept")]
|
||||
public IActionResult ThrowsWhenDurationIsNotSet()
|
||||
{
|
||||
return Content("Hello World!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ResponseCacheWebSite.Controllers
|
||||
{
|
||||
public class CacheProfilesController
|
||||
{
|
||||
[HttpGet("/CacheProfiles/PublicCache30Sec")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec")]
|
||||
public string PublicCache30Sec()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfiles/PrivateCache30Sec")]
|
||||
[ResponseCache(CacheProfileName = "PrivateCache30Sec")]
|
||||
public string PrivateCache30Sec()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfiles/NoCache")]
|
||||
[ResponseCache(CacheProfileName = "NoCache")]
|
||||
public string NoCache()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfiles/CacheProfileAddParameter")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec", VaryByHeader = "Accept")]
|
||||
public string CacheProfileAddParameter()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfiles/CacheProfileOverride")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec", Duration = 10)]
|
||||
public string CacheProfileOverride()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfiles/FallbackToFilter")]
|
||||
public string FallbackToFilter()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ResponseCacheWebSite.Controllers
|
||||
{
|
||||
public class CacheProfilesOverridesController
|
||||
{
|
||||
[HttpGet("/CacheProfileOverrides/PublicCache30SecTo15Sec")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec", Duration = 15)]
|
||||
public string PublicCache30SecTo15Sec()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfileOverrides/PublicCache30SecToPrivateCache")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec", Location = ResponseCacheLocation.Client)]
|
||||
public string PublicCache30SecToPrivateCache()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfileOverrides/PublicCache30SecToNoStore")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec", NoStore = true)]
|
||||
public string PublicCache30SecToNoStore()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfileOverrides/PublicCache30SecWithVaryByAcceptToVaryByTest")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec", VaryByHeader = "Test")]
|
||||
public string PublicCache30SecWithVaryByAcceptToVaryByTest()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
[HttpGet("/CacheProfileOverrides/PublicCache30SecWithVaryByAcceptToVaryByNone")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec", VaryByHeader = null)]
|
||||
public string PublicCache30SecWithVaryByAcceptToVaryByNone()
|
||||
{
|
||||
return "Hello World!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ResponseCacheWebSite
|
||||
{
|
||||
[ResponseCache(Duration = 100, Location = ResponseCacheLocation.Any, VaryByHeader = "Accept")]
|
||||
public class ClassLevelCacheController
|
||||
{
|
||||
[HttpGet("/ClassLevelCache/GetHelloWorld")]
|
||||
public string GetHelloWorld()
|
||||
{
|
||||
return "Hello, World!";
|
||||
}
|
||||
|
||||
[HttpGet("/ClassLevelCache/GetFooBar")]
|
||||
public string GetFooBar()
|
||||
{
|
||||
return "Foo Bar!";
|
||||
}
|
||||
|
||||
[HttpGet("/ClassLevelCache/ConflictExistingHeader")]
|
||||
[ResponseCache(Duration = 20)]
|
||||
public string ConflictExistingHeader()
|
||||
{
|
||||
return "Conflict";
|
||||
}
|
||||
|
||||
[HttpGet("/ClassLevelCache/DoNotCacheThisAction")]
|
||||
[ResponseCache(NoStore = true, Duration = 0, Location = ResponseCacheLocation.None)]
|
||||
public string DoNotCacheThisAction()
|
||||
{
|
||||
return "Conflict";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ResponseCacheWebSite
|
||||
{
|
||||
[ResponseCache(NoStore = true, Location = ResponseCacheLocation.None, Duration = 0)]
|
||||
public class ClassLevelNoStoreController
|
||||
{
|
||||
[HttpGet("/ClassLevelNoStore/GetHelloWorld")]
|
||||
public string GetHelloWorld()
|
||||
{
|
||||
return "Hello, World!";
|
||||
}
|
||||
|
||||
[HttpGet("/ClassLevelNoStore/CacheThisAction")]
|
||||
[ResponseCache(VaryByHeader = "Accept", Duration = 10)]
|
||||
public string CacheThisAction()
|
||||
{
|
||||
return "Conflict";
|
||||
}
|
||||
|
||||
[HttpGet("/ClassLevelNoStore/CacheThisActionWithProfileSettings")]
|
||||
[ResponseCache(CacheProfileName = "PublicCache30Sec", VaryByHeader = "Accept")]
|
||||
public string CacheThisActionWithProfileSettings()
|
||||
{
|
||||
return "Conflict";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>bdeebe09-c0c4-433c-b0b8-8478c9776996</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>63072</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ResponseCacheWebSite
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMvc(options =>
|
||||
{
|
||||
options.CacheProfiles.Add(
|
||||
"PublicCache30Sec", new CacheProfile
|
||||
{
|
||||
Duration = 30,
|
||||
Location = ResponseCacheLocation.Any
|
||||
});
|
||||
|
||||
options.CacheProfiles.Add(
|
||||
"PrivateCache30Sec", new CacheProfile
|
||||
{
|
||||
Duration = 30,
|
||||
Location = ResponseCacheLocation.Client
|
||||
});
|
||||
|
||||
options.CacheProfiles.Add(
|
||||
"NoCache", new CacheProfile
|
||||
{
|
||||
NoStore = true,
|
||||
Duration = 0,
|
||||
Location = ResponseCacheLocation.None
|
||||
});
|
||||
|
||||
options.CacheProfiles.Add(
|
||||
"PublicCache30SecVaryByAcceptHeader", new CacheProfile
|
||||
{
|
||||
Duration = 30,
|
||||
Location = ResponseCacheLocation.Any,
|
||||
VaryByHeader = "Accept"
|
||||
});
|
||||
|
||||
options.Filters.Add(new ResponseCacheFilter(new CacheProfile
|
||||
{
|
||||
NoStore = true,
|
||||
VaryByHeader = "TestDefault",
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseCultureReplacer();
|
||||
app.UseMvcWithDefaultRoute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
|
||||
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
},
|
||||
"webroot": "wwwroot"
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
ResponseCacheWebSite
|
||||
===
|
||||
|
||||
This web site illustrates how to use response caching.
|
||||
|
|
@ -1 +0,0 @@
|
|||
HelloWorld
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>a192e504-2881-41dc-90d1-b7f1dd1134e8</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>49643</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
|
||||
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
},
|
||||
"webroot": "wwwroot"
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
HelloWorld
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using ValidationWebSite.Models;
|
||||
|
||||
namespace ValidationWebSite.AnotherArea.Controllers
|
||||
{
|
||||
[Area("AnotherAria")]
|
||||
[Route("[Area]/[Controller]/[Action]", Order = -2)]
|
||||
public class RemoteAttribute_VerifyController : Controller
|
||||
{
|
||||
// Demonstrates validation action when AdditionalFields causes client to send multiple values.
|
||||
[HttpGet]
|
||||
public IActionResult IsIdAvailable(Person person)
|
||||
{
|
||||
return Json(data: string.Format(
|
||||
"/AnotherAria/RemoteAttribute_Verify/IsIdAvailable rejects '{0}' with '{1}', '{2}', and '{3}'.",
|
||||
person.UserId4,
|
||||
person.UserId1,
|
||||
person.UserId2,
|
||||
person.UserId3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using ValidationWebSite.ViewModels;
|
||||
|
||||
namespace ValidationWebSite.Controllers
|
||||
{
|
||||
public class ModelMetadataTypeValidationController : Controller
|
||||
{
|
||||
[HttpPost]
|
||||
public object ValidateProductViewModelIncludingMetadata([FromBody] ProductViewModel product)
|
||||
{
|
||||
return CreateValidationDictionary();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public object ValidateSoftwareViewModelIncludingMetadata([FromBody] SoftwareViewModel software)
|
||||
{
|
||||
return CreateValidationDictionary();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public object TryValidateModelAfterClearingValidationErrorInParameter(
|
||||
[Required, MaxLength(3), StringLength(10, MinimumLength = 3)] string theImpossibleString,
|
||||
[FromBody] ProductViewModel product)
|
||||
{
|
||||
// Clear ModelState entry. TryValidateModel should not add entries except those found within the
|
||||
// passed model.
|
||||
ModelState.ClearValidationState("theImpossibleString");
|
||||
|
||||
TryValidateModel(product);
|
||||
|
||||
return CreateValidationDictionary();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public object TryValidateModelWithCollectionsModel([FromBody] List<ProductViewModel> products)
|
||||
{
|
||||
TryValidateModel(products);
|
||||
|
||||
return CreateValidationDictionary();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public object TryValidateModelSoftwareViewModelWithPrefix()
|
||||
{
|
||||
var softwareViewModel = new SoftwareViewModel
|
||||
{
|
||||
Category = "Technology",
|
||||
CompanyName = "Microsoft",
|
||||
Contact = "4258393231",
|
||||
Country = "UK",
|
||||
DatePurchased = new DateTime(2010, 10, 10),
|
||||
Price = 110,
|
||||
Version = "2"
|
||||
};
|
||||
|
||||
TryValidateModel(softwareViewModel, "software");
|
||||
|
||||
return CreateValidationDictionary();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public object TryValidateModelValidModelNoPrefix()
|
||||
{
|
||||
var softwareViewModel = new SoftwareViewModel
|
||||
{
|
||||
Category = "Technology",
|
||||
CompanyName = "Microsoft",
|
||||
Contact = "4258393231",
|
||||
Country = "USA",
|
||||
DatePurchased = new DateTime(2010, 10, 10),
|
||||
Name = "MVC",
|
||||
Price = 110,
|
||||
Version = "2"
|
||||
};
|
||||
|
||||
TryValidateModel(softwareViewModel);
|
||||
|
||||
return CreateValidationDictionary();
|
||||
}
|
||||
|
||||
private Dictionary<string, string> CreateValidationDictionary()
|
||||
{
|
||||
var result = new Dictionary<string, string>();
|
||||
foreach (var item in ModelState)
|
||||
{
|
||||
var errorMessage = string.Empty;
|
||||
foreach (var error in item.Value.Errors)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
errorMessage = errorMessage + error.ErrorMessage;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(errorMessage))
|
||||
{
|
||||
result.Add(item.Key, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace ValidationWebSite.Models
|
||||
{
|
||||
public class Person
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
// Controller in current area.
|
||||
[Remote("IsIdAvailable", "RemoteAttribute_Verify")]
|
||||
public string UserId1 { get; set; }
|
||||
|
||||
// Controller in root area.
|
||||
[Remote("IsIdAvailable", "RemoteAttribute_Verify", null, HttpMethod = "Post")]
|
||||
public string UserId2 { get; set; }
|
||||
|
||||
// Controller in MyArea area.
|
||||
[Remote(
|
||||
"IsIdAvailable",
|
||||
"RemoteAttribute_Verify",
|
||||
"Aria",
|
||||
ErrorMessage = "/Aria/RemoteAttribute_Verify/IsIdAvailable rejects you.")]
|
||||
public string UserId3 { get; set; }
|
||||
|
||||
// Controller in AnotherArea area.
|
||||
[Remote(
|
||||
"IsIdAvailable",
|
||||
"RemoteAttribute_Verify",
|
||||
"AnotherAria",
|
||||
AdditionalFields = "UserId1, UserId2, UserId3")]
|
||||
public string UserId4 { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
ValidationWebSite
|
||||
===
|
||||
|
||||
This web site illustrates how to add `ModelMetadataType` attribute and validate the models during model binding.
|
||||
It also show how to validate models using the `TryValidateModel` API as well as how to use the `RemoteAttribute` as
|
||||
part of validation. `RemoteAttribute` scenarios shown here all work in combination with attribute routing.
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
@{
|
||||
Layout = "/Views/Shared/_Layout.cshtml";
|
||||
ViewBag.Title = "Error";
|
||||
}
|
||||
|
||||
<h1>Error.</h1>
|
||||
<h2>An error occurred while processing your request.</h2>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
@{
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
|
||||
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
},
|
||||
"exclude": [
|
||||
"wwwroot",
|
||||
"node_modules",
|
||||
"bower_components"
|
||||
],
|
||||
"publishExclude": [
|
||||
"**.user",
|
||||
"**.vspscc"
|
||||
],
|
||||
"webroot": "wwwroot"
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
HelloWorld
|
||||
Loading…
Reference in New Issue