Including Mvc.js script which enables Mvc.stringify(data) used in JQuery.Post() to send data understandable by MVC.
Adding Bower and Grunt components to pull JQuery from an appropriate source. Addressing PR Comments.
This commit is contained in:
parent
f4ea1b82fa
commit
eeabe27606
|
|
@ -0,0 +1,23 @@
|
|||
// 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.Linq;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace MvcSample.Web.Controllers
|
||||
{
|
||||
public class FormUrlEncodedController : Controller
|
||||
{
|
||||
[Route("[controller]")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[Route("[controller]/[action]")]
|
||||
public bool IsValidPerson(Person person)
|
||||
{
|
||||
return ModelState.IsValid && person.PastJobs.Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// 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 MvcSample.Web
|
||||
{
|
||||
public class Address
|
||||
{
|
||||
[Required]
|
||||
public string Street { get; set; }
|
||||
|
||||
[Required]
|
||||
public string City { get; set; }
|
||||
|
||||
[Required]
|
||||
public string State { get; set; }
|
||||
|
||||
[Required]
|
||||
public int ZipCode { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// 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 MvcSample.Web
|
||||
{
|
||||
public class Job
|
||||
{
|
||||
[Required]
|
||||
public string JobTitle { get; set; }
|
||||
|
||||
[Required]
|
||||
public string EmployerName { get; set; }
|
||||
|
||||
[Required]
|
||||
public int Years { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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 System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace MvcSample.Web
|
||||
{
|
||||
public class Person
|
||||
{
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Required]
|
||||
public Address Address { get; set; }
|
||||
|
||||
[Required]
|
||||
public IEnumerable<Job> PastJobs { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>JQuery FormUrlEncoded example</title>
|
||||
<script src="~/lib/jquery/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="~/Scripts/MVC.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
$('#personButton').click(function () {
|
||||
var data = {
|
||||
Name: 'SamplePerson',
|
||||
Address: {
|
||||
Street: 'SampleStreet',
|
||||
City: "SampleCity",
|
||||
State: "SampleState",
|
||||
ZipCode: 11
|
||||
},
|
||||
PastJobs: [
|
||||
{
|
||||
JobTitle: "SampleJob1",
|
||||
EmployerName: 'Employer1',
|
||||
Years: 2
|
||||
},
|
||||
{
|
||||
JobTitle: "SampleJob2",
|
||||
EmployerName: 'Employer2',
|
||||
Years: 4
|
||||
},
|
||||
{
|
||||
JobTitle: "SampleJob3",
|
||||
EmployerName: 'Employer3',
|
||||
Years: 1
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
$.post('@Url.Action("IsValidPerson", "FormUrlEncoded")', MVC.stringify(data))
|
||||
.done(function (result) {
|
||||
if (result)
|
||||
{
|
||||
$("#validPerson").html("The submitted data belongs to a valid person.");
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#validPerson").html("The submitted data is invalid.");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="personButton" type="button">Click here to post person data</button><br /><br />
|
||||
<p id="validPerson"></p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "MvcSample.Web",
|
||||
"description": "Web site demonstrating various MVC features.",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"jquery": "1.11.2"
|
||||
},
|
||||
"exportsOverride": {
|
||||
"jquery": {
|
||||
"": "dist/jquery.{js,min.js,min.map}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
module.exports = function (grunt) {
|
||||
grunt.initConfig({
|
||||
bower: {
|
||||
install: {
|
||||
options: {
|
||||
targetDir: "wwwroot/lib",
|
||||
layout: "byComponent",
|
||||
cleanTargetDir: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// This command registers the default task which will install bower packages into wwwroot/lib
|
||||
grunt.registerTask("default", ["bower:install"]);
|
||||
|
||||
// The following line loads the grunt plugins.
|
||||
// This line needs to be at the end of this this file.
|
||||
grunt.loadNpmTasks("grunt-bower-task");
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"version": "0.0.0",
|
||||
"name": "MvcSample.Web",
|
||||
"private": true,
|
||||
"description": "Web site demonstrating various MVC features.",
|
||||
"devDependencies": {
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-bower-task": "^0.4.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -29,5 +29,17 @@
|
|||
"dependencies": { }
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"wwwroot",
|
||||
"node_modules",
|
||||
"bower_components"
|
||||
],
|
||||
"packExclude": [
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"**.kproj",
|
||||
"**.user",
|
||||
"**.vspscc"
|
||||
],
|
||||
"webroot": "wwwroot"
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
// 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.
|
||||
|
||||
var MVC = (function () {
|
||||
// Takes the data which needs to be converted to form-url encoded format understadable by MVC.
|
||||
// This does not depend on jQuery. Can be used independently.
|
||||
var _stringify = function (data) {
|
||||
// This holds the stringified result.
|
||||
var result = "";
|
||||
|
||||
if (typeof data !== "object")
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
for (var element in data) {
|
||||
if (data.hasOwnProperty(element)) {
|
||||
result += process(element, data[element]);
|
||||
}
|
||||
}
|
||||
|
||||
// An '&' is appended at the end. Removing it.
|
||||
return result.substring(0, result.length - 1);
|
||||
}
|
||||
|
||||
function process(key, value, prefix) {
|
||||
// Ignore functions.
|
||||
if (typeof value === "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Object.prototype.toString.call(value) === '[object Array]') {
|
||||
var result = "";
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
var tempPrefix = (prefix || key) + "[" + i + "]";
|
||||
result += process(key, value[i], tempPrefix);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else if (typeof value === "object") {
|
||||
var result = "";
|
||||
for (var prop in value) {
|
||||
// This is to prevent looping through inherited proeprties.
|
||||
if (value.hasOwnProperty(prop)) {
|
||||
var tempPrefix = (prefix || key) + "." + prop;
|
||||
result += process(prop, value[prop], tempPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return encodeURIComponent(prefix || key) + "=" + encodeURIComponent(value) + "&";
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// Converts a Json object into MVC understandable format
|
||||
// when submitted as form-url-encoded data.
|
||||
stringify: _stringify
|
||||
};
|
||||
})()
|
||||
|
|
@ -6,6 +6,7 @@ using System.IO;
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Mvc.Xml;
|
||||
|
|
@ -51,6 +52,55 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Name=SamplePerson&Address.Street=SampleStreet&Address.City=SampleCity&" +
|
||||
"Address.State=SampleState&Address.ZipCode=11&PastJobs[0].JobTitle=SampleJob1&" +
|
||||
"PastJobs[0].EmployerName=Employer1&PastJobs[0].Years=2&PastJobs[1].JobTitle=SampleJob2&" +
|
||||
"PastJobs[1].EmployerName=Employer2&PastJobs[1].Years=4&PastJobs[2].JobTitle=SampleJob3&" +
|
||||
"PastJobs[2].EmployerName=Employer3&PastJobs[2].Years=1", "true")]
|
||||
// Input with some special characters
|
||||
[InlineData("Name=SamplePerson&Address.Street=SampleStre'et&Address.City=S\ampleCity&" +
|
||||
"Address.State=SampleState&Address.ZipCode=11&PastJobs[0].JobTitle=S~ampleJob1&" +
|
||||
"PastJobs[0].EmployerName=Employer1&PastJobs[0].Years=2&PastJobs[1].JobTitle=SampleJob2&" +
|
||||
"PastJobs[1].EmployerName=Employer2&PastJobs[1].Years=4&PastJobs[2].JobTitle=SampleJob3&" +
|
||||
"PastJobs[2].EmployerName=Employer3&PastJobs[2].Years=1", "true")]
|
||||
[InlineData("Name=SamplePerson", "false")]
|
||||
public async Task FormUrlEncoded_ReturnsAppropriateResults(string input, string expectedOutput)
|
||||
{
|
||||
using (TestHelper.ReplaceCallContextServiceLocationService(_services))
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/FormUrlEncoded/IsValidPerson");
|
||||
request.Content = new StringContent(input, Encoding.UTF8, "application/x-www-form-urlencoded");
|
||||
|
||||
// Act
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedOutput, await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FormUrlEncoded_Index_ReturnSuccess()
|
||||
{
|
||||
using (TestHelper.ReplaceCallContextServiceLocationService(_services))
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("http://localhost/FormUrlEncoded");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(response);
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Home_NotFoundAction_Returns404()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue