+ {
+ { "UserId1", "Jane1" },
+ { "UserId2", "Jane2" },
+ { "UserId3", "Jane3" },
+ { "UserId4", "Jane4" },
+ };
+ var content = new FormUrlEncodedContent(contentDictionary);
+
+ // Act
+ var response = await client.PostAsync(url, content);
+
+ // Assert
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
+ Assert.Equal("utf-8", response.Content.Headers.ContentType.CharSet);
+ var responseContent = await response.Content.ReadAsStringAsync();
+ Assert.Equal(expectedContent, responseContent);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/AnotherArea/Controllers/RemoteAttribute_VerifyController.cs b/test/WebSites/ValidationWebSite/AnotherArea/Controllers/RemoteAttribute_VerifyController.cs
new file mode 100644
index 0000000000..7273275381
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/AnotherArea/Controllers/RemoteAttribute_VerifyController.cs
@@ -0,0 +1,25 @@
+// 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 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));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/Controllers/RemoteAttribute_HomeController.cs b/test/WebSites/ValidationWebSite/Controllers/RemoteAttribute_HomeController.cs
new file mode 100644
index 0000000000..0dc6221510
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/Controllers/RemoteAttribute_HomeController.cs
@@ -0,0 +1,41 @@
+// 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 Microsoft.AspNet.Mvc;
+using ValidationWebSite.Models;
+
+namespace ValidationWebSite.Controllers
+{
+ public class RemoteAttribute_HomeController : Controller
+ {
+ private static Person _person;
+
+ [HttpGet]
+ [Route("[Controller]/[Action]")]
+ public IActionResult Create()
+ {
+ return View();
+ }
+
+ [HttpPost]
+ [Route("[Controller]/[Action]")]
+ public IActionResult Create(Person person)
+ {
+ ModelState.Remove("id");
+ if (!ModelState.IsValid)
+ {
+ return View(person);
+ }
+
+ _person = person;
+ return RedirectToAction(nameof(Details));
+ }
+
+ [Route("", Name = "Home", Order = -1)]
+ [Route("[Controller]/Index")]
+ public IActionResult Details()
+ {
+ return View(_person);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/Controllers/RemoteAttribute_VerifyController.cs b/test/WebSites/ValidationWebSite/Controllers/RemoteAttribute_VerifyController.cs
new file mode 100644
index 0000000000..2815414fb3
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/Controllers/RemoteAttribute_VerifyController.cs
@@ -0,0 +1,18 @@
+// 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 Microsoft.AspNet.Mvc;
+
+namespace ValidationWebSite.Controllers
+{
+ [Route("[Controller]/[Action]")]
+ public class RemoteAttribute_VerifyController : Controller
+ {
+ // This action is overloaded and may receive requests to validate either UserId1 or UserId2.
+ [AcceptVerbs("Get", "Post")]
+ public IActionResult IsIdAvailable(string userId1, string userId2)
+ {
+ return Json(data: string.Format("/RemoteAttribute_Verify/IsIdAvailable rejects {0}.", userId1 ?? userId2));
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/Models/Person.cs b/test/WebSites/ValidationWebSite/Models/Person.cs
new file mode 100644
index 0000000000..db2cf03df0
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/Models/Person.cs
@@ -0,0 +1,36 @@
+// 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 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; }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/MyArea/Controllers/RemoteAttribute_HomeController.cs b/test/WebSites/ValidationWebSite/MyArea/Controllers/RemoteAttribute_HomeController.cs
new file mode 100644
index 0000000000..b42cf4c6be
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/MyArea/Controllers/RemoteAttribute_HomeController.cs
@@ -0,0 +1,41 @@
+// 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 Microsoft.AspNet.Mvc;
+using ValidationWebSite.Models;
+
+namespace ValidationWebSite.MyArea.Controllers
+{
+ [Area("Aria")]
+ [Route("[Area]/[Controller]/[Action]", Order = -2)]
+ public class RemoteAttribute_HomeController : Controller
+ {
+ private static Person _person;
+
+ [HttpGet]
+ public IActionResult Create()
+ {
+ return View();
+ }
+
+ [HttpPost]
+ public IActionResult Create(Person person)
+ {
+ ModelState.Remove("id");
+ if (!ModelState.IsValid)
+ {
+ return View(person);
+ }
+
+ _person = person;
+ return RedirectToAction(nameof(Details));
+ }
+
+ [Route("/[Area]", Name = "AriaHome", Order = -3)]
+ [Route("/[Area]/[Controller]/Index", Order = -2)]
+ public IActionResult Details()
+ {
+ return View(_person);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/MyArea/Controllers/RemoteAttribute_VerifyController.cs b/test/WebSites/ValidationWebSite/MyArea/Controllers/RemoteAttribute_VerifyController.cs
new file mode 100644
index 0000000000..ace49ede39
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/MyArea/Controllers/RemoteAttribute_VerifyController.cs
@@ -0,0 +1,20 @@
+// 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 Microsoft.AspNet.Mvc;
+
+namespace ValidationWebSite.MyArea.Controllers
+{
+ [Area("Aria")]
+ 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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/Startup.cs b/test/WebSites/ValidationWebSite/Startup.cs
index 71cfda98e5..5c0d932f61 100644
--- a/test/WebSites/ValidationWebSite/Startup.cs
+++ b/test/WebSites/ValidationWebSite/Startup.cs
@@ -12,6 +12,9 @@ namespace ValidationWebSite
{
var configuration = app.GetTestConfiguration();
+ // Set up file serving for JavaScript files.
+ app.UseFileServer();
+
// Set up application services
app.UseServices(services =>
{
diff --git a/test/WebSites/ValidationWebSite/Views/Shared/Create.cshtml b/test/WebSites/ValidationWebSite/Views/Shared/Create.cshtml
new file mode 100644
index 0000000000..eb0666c89f
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/Views/Shared/Create.cshtml
@@ -0,0 +1,75 @@
+@model ValidationWebSite.Models.Person
+@{
+ object areaObject;
+ ViewContext.ActionDescriptor.RouteValueDefaults.TryGetValue("area", out areaObject);
+ var areaName = (areaObject as string) ?? "root";
+
+ ViewBag.Title = "Create in " + areaName + " area.";
+}
+
+@ViewBag.Title
+@using (Html.BeginForm())
+{
+
+}
+
+
+ @Html.ActionLink("Go back to home", "Details")
+
+
+@section Scripts {
+ @* Until script helpers are available, add script references manually. *@
+ @* @Scripts.Render("~/bundles/jqueryval") *@
+
+
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/Views/Shared/Details.cshtml b/test/WebSites/ValidationWebSite/Views/Shared/Details.cshtml
new file mode 100644
index 0000000000..f86281b95c
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/Views/Shared/Details.cshtml
@@ -0,0 +1,76 @@
+@model ValidationWebSite.Models.Person
+@{
+ object areaObject;
+ ViewContext.ActionDescriptor.RouteValueDefaults.TryGetValue("area", out areaObject);
+ var areaName = (areaObject as string) ?? "root";
+
+ ViewBag.Title = "Details in " + areaName + " area.";
+}
+
+@ViewBag.Title
+
+
Person
+
+
+
+ -
+ @Html.DisplayNameFor(model => model.Id)
+
+
+ -
+ @Html.DisplayFor(model => model.Id)
+
+
+
+
+ -
+ @Html.DisplayNameFor(model => model.UserId1)
+
+
+ -
+ @Html.DisplayFor(model => model.UserId1)
+
+
+
+
+ -
+ @Html.DisplayNameFor(model => model.UserId2)
+
+
+ -
+ @Html.DisplayFor(model => model.UserId2)
+
+
+
+
+ -
+ @Html.DisplayNameFor(model => model.UserId3)
+
+
+ -
+ @Html.DisplayFor(model => model.UserId3)
+
+
+
+
+ -
+ @Html.DisplayNameFor(model => model.UserId4)
+
+
+ -
+ @Html.DisplayFor(model => model.UserId4)
+
+
+
+
+
+ @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")
+ }
+
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/Views/Shared/Error.cshtml b/test/WebSites/ValidationWebSite/Views/Shared/Error.cshtml
new file mode 100644
index 0000000000..5d73bf597b
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/Views/Shared/Error.cshtml
@@ -0,0 +1,7 @@
+@{
+ Layout = "/Views/Shared/_Layout.cshtml";
+ ViewBag.Title = "Error";
+}
+
+Error.
+An error occurred while processing your request.
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/Views/Shared/_Layout.cshtml b/test/WebSites/ValidationWebSite/Views/Shared/_Layout.cshtml
new file mode 100644
index 0000000000..d403cd1e79
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/Views/Shared/_Layout.cshtml
@@ -0,0 +1,31 @@
+
+
+
+
+
+ @ViewBag.Title - My ASP.NET Application
+
+
+
+
+
+ @Html.ActionLink("Validation web site", "Details", "RemoteAttribute_Home", routeValues: new { area = (object)null })
+
+
+
+
+ - @Html.ActionLink("Home", "Details", "RemoteAttribute_Home", routeValues: new { area = string.Empty })
+ - @Html.ActionLink("Aria Home", "Details", "RemoteAttribute_Home", routeValues: new { area = "Aria" })
+
+
+
+
+
+
+ @RenderBody()
+
+
+
+ @RenderSection("scripts", required: false)
+
+
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/Views/Shared/_ViewStart.cshtml b/test/WebSites/ValidationWebSite/Views/Shared/_ViewStart.cshtml
new file mode 100644
index 0000000000..efda124b1f
--- /dev/null
+++ b/test/WebSites/ValidationWebSite/Views/Shared/_ViewStart.cshtml
@@ -0,0 +1,3 @@
+@{
+ Layout = "~/Views/Shared/_Layout.cshtml";
+}
\ No newline at end of file
diff --git a/test/WebSites/ValidationWebSite/wwwroot/readme.md b/test/WebSites/ValidationWebSite/wwwroot/readme.md
index 047eb18bae..7317fcaa24 100644
Binary files a/test/WebSites/ValidationWebSite/wwwroot/readme.md and b/test/WebSites/ValidationWebSite/wwwroot/readme.md differ