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:
sornaks 2015-02-20 07:56:26 -08:00
parent f4ea1b82fa
commit eeabe27606
11 changed files with 311 additions and 0 deletions

View File

@ -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();
}
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}
}

View File

@ -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>

View File

@ -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}"
}
}
}

View File

@ -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");
};

View File

@ -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"
}
}

View File

@ -29,5 +29,17 @@
"dependencies": { }
}
},
"exclude": [
"wwwroot",
"node_modules",
"bower_components"
],
"packExclude": [
"node_modules",
"bower_components",
"**.kproj",
"**.user",
"**.vspscc"
],
"webroot": "wwwroot"
}

View File

@ -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
};
})()

View File

@ -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()
{