MvcTagHelpers tests for

1) A few `<input/>` tag helpers in a partial view invoked (`@Html.PartialAsync()`) in a loop within a `@for` inside an `using @Html.BeginForm()` block.
2) A custom template e.g. EditorTemplates/MyType.cshtml containing a mix of `<input/>`, `<select/>`, and various input HTML helpers invoked (`@Html.Editor[For]()`) in a loop within a `@for` inside an `using @Html.BeginForm()` block.
3)  `<select/>` tag helpers with an `using @Html.BeginForm()` block
4) HTML helpers in the <form/> tag helper
This commit is contained in:
Youngjune Hong 2015-01-09 17:59:25 -08:00
parent cbea96cf37
commit 40e479c915
18 changed files with 610 additions and 72 deletions

View File

@ -0,0 +1,23 @@

<html>
<body>
<form action="/MvcTagHelper_Home/CreateWarehouse" method="post"> <div>
<label class="warehouse" for="City">City</label>
<input size="50" type="text" data-val="true" data-val-minlength="The field City must be a string or array type with a minimum length of &#39;2&#39;." data-val-minlength-min="2" id="City" name="City" value="" />
<span class="field-validation-valid" data-valmsg-for="City" data-valmsg-replace="true"></span>
</div>
<div>
<label class="warehouse" for="Product">Product</label>
<select data-val="true" data-val-range="The field Product must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" id="Product" name="Product"><option value="0">Product_0</option>
<option value="1">Product_1</option>
<option value="2">Product_2</option>
</select>
<span class="field-validation-valid" data-valmsg-for="Product" data-valmsg-replace="true"></span>
</div>
<div class="warehouse validation-summary-valid" data-valmsg-summary="true"><ul><li style="display:none"></li>
</ul></div>
<input type="submit"></input>
</form></body>
</html>

View File

@ -0,0 +1,47 @@

<html>
<body>
<form action="/MvcTagHelper_Home/EditWarehouse" method="post">
<div>
City_1
<input type="text" data-val="true" data-val-minlength="The field City must be a string or array type with a minimum length of &#39;2&#39;." data-val-minlength-min="2" id="City" name="City" value="City_1" />
</div>
<div>
<label>Address</label>
<textarea id="Employee_Address" name="Employee.Address">
Address_1</textarea>;
</div>
<div>
<label for="Employee_Password">Password</label>
<input data-val="true" data-val-required="The Password field is required." id="Employee_Password" name="Employee.Password" type="password" />
</div>
<div>
<label>PhoneNumber</label>
<input id="Employee_PhoneNumber" name="Employee.PhoneNumber" type="text" value="PhoneNumber_1" />
</div>
<div>
<label for="Employee_Name">Employee.Name</label>
<input type="text" id="Employee_Name" name="Employee.Name" value="EmployeeName_1" />
<span class="field-validation-valid" data-valmsg-for="Employee.Name" data-valmsg-replace="true"></span>
</div>
<div>
<label for="Employee_Gender">Gender</label>
<input checked="checked" id="Employee_Gender" name="Employee.Gender" type="radio" value="Female" /> Female
<input id="Employee_Gender" name="Employee.Gender" type="radio" value="Male" /> Male
</div>
<div>
<label for="Employee_OfficeNumber">OfficeNumber</label>
<select id="Employee_OfficeNumber" name="Employee.OfficeNumber"><option>1001</option>
<option>1002</option>
</select>
</div>
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" id="Employee_Number" name="Employee.Number" type="hidden" value="1" />
<div class="validation-summary-valid" data-valmsg-summary="true"><ul><li style="display:none"></li>
</ul></div>
<input type="submit"></input>
</form>
</body>
</html>

View File

@ -0,0 +1,104 @@

<html>
<body>
<form action="/MvcTagHelper_Home/EmployeeList" method="post">
<div>
<label for="z0__Number">Number</label>
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" disabled="disabled" id="z0__Number" name="[0].Number" readonly="readonly" type="text" value="0" />
<input class="form-control" type="number" id="z0__Number" name="[0].Number" value="0" />
</div>
<div>
<label class="employee" for="z0__Name">Name</label>
<textarea id="z0__Name" name="[0].Name">
EmployeeName_0</textarea>
</div>
<div>
<label class="employee" for="z0__PhoneNumber">PhoneNumber</label>
<input type="tel" id="z0__PhoneNumber" name="[0].PhoneNumber" value="" />
</div>
<div>
<label class="employee" for="z0__Gender">Gender</label>
<select id="z0__Gender" name="[0].Gender"><option selected="selected">Male</option>
<option>Female</option>
</select>
</div>
<div>
<label class="employee" for="z0__Remote">Remote</label>
<input id="z0__Remote" name="[0].Remote" type="checkbox" value="true" /><input name="[0].Remote" type="hidden" value="false" />
</div>
<div>
<label class="employee" for="z0__OfficeNumber">OfficeNumber</label>
<select id="z0__OfficeNumber" name="[0].OfficeNumber"><option>1001</option>
<option>1002</option>
</select>
</div>
<div>
<label for="z1__Number">Number</label>
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" disabled="disabled" id="z1__Number" name="[1].Number" readonly="readonly" type="text" value="1" />
<input class="form-control" type="number" id="z1__Number" name="[1].Number" value="1" />
</div>
<div>
<label class="employee" for="z1__Name">Name</label>
<textarea id="z1__Name" name="[1].Name">
EmployeeName_1</textarea>
</div>
<div>
<label class="employee" for="z1__PhoneNumber">PhoneNumber</label>
<input type="tel" id="z1__PhoneNumber" name="[1].PhoneNumber" value="" />
</div>
<div>
<label class="employee" for="z1__Gender">Gender</label>
<select id="z1__Gender" name="[1].Gender"><option>Male</option>
<option selected="selected">Female</option>
</select>
</div>
<div>
<label class="employee" for="z1__Remote">Remote</label>
<input id="z1__Remote" name="[1].Remote" type="checkbox" value="true" /><input name="[1].Remote" type="hidden" value="false" />
</div>
<div>
<label class="employee" for="z1__OfficeNumber">OfficeNumber</label>
<select id="z1__OfficeNumber" name="[1].OfficeNumber"><option>1001</option>
<option selected="selected">1002</option>
</select>
</div>
<div>
<label for="z2__Number">Number</label>
<input data-val="true" data-val-range="The field Number must be between 1 and 100." data-val-range-max="100" data-val-range-min="1" disabled="disabled" id="z2__Number" name="[2].Number" readonly="readonly" type="text" value="2" />
<input class="form-control" type="number" id="z2__Number" name="[2].Number" value="2" />
</div>
<div>
<label class="employee" for="z2__Name">Name</label>
<textarea id="z2__Name" name="[2].Name">
EmployeeName_2</textarea>
</div>
<div>
<label class="employee" for="z2__PhoneNumber">PhoneNumber</label>
<input type="tel" id="z2__PhoneNumber" name="[2].PhoneNumber" value="" />
</div>
<div>
<label class="employee" for="z2__Gender">Gender</label>
<select id="z2__Gender" name="[2].Gender"><option selected="selected">Male</option>
<option>Female</option>
</select>
</div>
<div>
<label class="employee" for="z2__Remote">Remote</label>
<input checked="checked" id="z2__Remote" name="[2].Remote" type="checkbox" value="true" /><input name="[2].Remote" type="hidden" value="false" />
</div>
<div>
<label class="employee" for="z2__OfficeNumber">OfficeNumber</label>
<select id="z2__OfficeNumber" name="[2].OfficeNumber"><option>1001</option>
<option>1002</option>
</select>
</div> <input type="submit" />
</form></body>
</html>

View File

@ -18,12 +18,9 @@
</div>
<div>
<label class="order" for="Products">Products</label>
<select Multiple="multiple" id="Products" name="Products"><option value="7">Product_7</option>
<option value="8">Product_8</option>
<option selected="selected" value="9">Product_9</option>
<option value="10">Product_10</option>
<option value="11">Product_11</option>
<option value="12">Product_12</option>
<select Multiple="multiple" id="Products" name="Products"><option value="0">Product_0</option>
<option value="1">Product_1</option>
<option selected="selected" value="2">Product_2</option>
</select>
</div>
<div>

View File

@ -0,0 +1,60 @@

<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<form action="/MvcTagHelper_Product" method="post">
<div>
<label class="product" for="HomePage">HomePage</label>
<input size="50" type="url" id="HomePage" name="HomePage" value="http://www.contoso.com/" />
</div>
<div>
<label class="product" for="Number">Number</label>
<input type="number" id="Number" name="Number" value="0" />
</div>
<div>
<label class="product" for="ProductName">ProductName</label>
<input type="text" data-val="true" data-val-required="The ProductName field is required." id="ProductName" name="ProductName" value="Product_0" />
</div>
<div>
<label class="product" for="Description">Description</label>
<textarea rows="4" cols="50" class="product" id="Description" name="Description">
</textarea>
</div>
<div>
<label class="product" for="HomePage">HomePage</label>
<input size="50" type="url" id="HomePage" name="HomePage" value="" />
</div>
<div>
<label class="product" for="Number">Number</label>
<input type="number" id="Number" name="Number" value="1" />
</div>
<div>
<label class="product" for="ProductName">ProductName</label>
<input type="text" id="ProductName" name="ProductName" value="Product_1" />
</div>
<div>
<label class="product" for="Description">Description</label>
<textarea rows="4" cols="50" class="product" id="Description" name="Description">
</textarea>
</div>
<div>
<label class="product" for="HomePage">HomePage</label>
<input size="50" type="url" id="HomePage" name="HomePage" value="" />
</div>
<div>
<label class="product" for="Number">Number</label>
<input type="number" id="Number" name="Number" value="2" />
</div>
<div>
<label class="product" for="ProductName">ProductName</label>
<input type="text" id="ProductName" name="ProductName" value="Product_2" />
</div>
<div>
<label class="product" for="Description">Description</label>
<textarea rows="4" cols="50" class="product" id="Description" name="Description">
Product_2 desription</textarea>
</div> <input type="submit"></input>
</form></body>
</html>

View File

@ -26,6 +26,14 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
[InlineData("Order", "/MvcTagHelper_Order/Submit")]
[InlineData("Product", null)]
[InlineData("Customer", "/Customer/MvcTagHelper_Customer")]
// Testing InputTagHelpers invoked in the partial views
[InlineData("ProductList", null)]
// Testing MvcTagHelpers invoked in the editor templates with the HTML helpers
[InlineData("EmployeeList", null)]
// Testing SelectTagHelper with Html.BeginForm
[InlineData("CreateWarehouse", null)]
// Testing the HTML helpers with FormTagHelper
[InlineData("EditWarehouse", null)]
public async Task MvcTagHelpers_GeneratesExpectedResults(string action, string antiForgeryPath)
{
// Arrange

View File

@ -12,27 +12,37 @@ namespace MvcTagHelpersWebSite.Controllers
{
public class MvcTagHelper_HomeController : Controller
{
private readonly List<Product> _products = new List<Product>();
public MvcTagHelper_HomeController()
{
_products.Add(new Product
{
ProductName = "Product_0",
Number = 0,
HomePage = new Uri("http://www.contoso.com")
});
_products.Add(new Product
{
ProductName = "Product_1",
Number = 1,
});
_products.Add(new Product
{
ProductName = "Product_2",
Number = 2,
Description = "Product_2 desription"
});
}
public IActionResult Order()
{
var products = new List<Product>();
products = new List<Product>();
ViewBag.Items = new SelectList(_products, "Number", "ProductName", 2);
for (int i = 7; i < 13; ++i)
{
products.Add(new Product()
{
ProductName = "Product_" + i,
Number = i,
PartNumbers = Enumerable.Range(1, 3).Select(n => string.Format("{0}-{1}", i, n))
});
}
ViewBag.Items = new SelectList(products, "Number", "ProductName", 9);
var order = new Order()
var order = new Order
{
Shipping = "UPSP",
Customer = new Customer()
Customer = new Customer
{
Key = "KeyA",
Number = 1,
@ -48,7 +58,7 @@ namespace MvcTagHelpersWebSite.Controllers
public IActionResult Product()
{
var product = new Product()
var product = new Product
{
HomePage = new System.Uri("http://www.contoso.com"),
Description = "Type the product description"
@ -70,5 +80,61 @@ namespace MvcTagHelpersWebSite.Controllers
{
return View();
}
public IActionResult ProductList()
{
return View(_products);
}
public IActionResult EmployeeList()
{
var employees = new List<Employee>();
employees.Add(new Employee
{
Name = "EmployeeName_0",
Number = 0,
Address = "Employee_0 address"
});
employees.Add(new Employee
{
Name = "EmployeeName_1",
Number = 1,
OfficeNumber = "1002",
Gender = Gender.Female
});
employees.Add(new Employee
{
Name = "EmployeeName_2",
Number = 2,
Remote = true
});
return View(employees);
}
public IActionResult CreateWarehouse()
{
ViewBag.Items = new SelectList(_products, "Number", "ProductName", 9);
return View();
}
public IActionResult EditWarehouse()
{
var warehouse = new Warehouse
{
City = "City_1",
Employee = new Employee
{
Name = "EmployeeName_1",
Number = 1,
Address = "Address_1",
PhoneNumber = "PhoneNumber_1",
Gender = Gender.Female
}
};
return View(warehouse);
}
}
}

View File

@ -1,56 +1,14 @@
// 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 MvcTagHelpersWebSite.Models
{
public class Customer
public class Customer : Person
{
[Range(1, 100)]
public int Number
{
get;
set;
}
public string Key
{
get;
set;
}
public string Name
{
get;
set;
}
[Required]
public string Password
{
get;
set;
}
[EnumDataType(typeof(Gender))]
public Gender Gender
{
get;
set;
}
public string PhoneNumber
{
get;
set;
}
[DataType(DataType.EmailAddress)]
public string Email
{
get;
set;
}
}
}

View File

@ -0,0 +1,26 @@
// 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.
namespace MvcTagHelpersWebSite.Models
{
public class Employee : Person
{
public string Address
{
get;
set;
}
public string OfficeNumber
{
get;
set;
}
public bool Remote
{
get;
set;
}
}
}

View File

@ -0,0 +1,50 @@
// 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 MvcTagHelpersWebSite.Models
{
public class Person
{
[Range(1, 100)]
public int Number
{
get;
set;
}
public string Name
{
get;
set;
}
[Required]
public string Password
{
get;
set;
}
[EnumDataType(typeof(Gender))]
public Gender Gender
{
get;
set;
}
public string PhoneNumber
{
get;
set;
}
[DataType(DataType.EmailAddress)]
public string Email
{
get;
set;
}
}
}

View File

@ -28,12 +28,6 @@ namespace MvcTagHelpersWebSite.Models
set;
}
public IEnumerable<string> PartNumbers
{
get;
set;
}
public Uri HomePage
{
get;

View File

@ -0,0 +1,30 @@
// 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 MvcTagHelpersWebSite.Models
{
public class Warehouse
{
[MinLength(2)]
public string City
{
get;
set;
}
[Range(1, 100)]
public int Product
{
get;
set;
}
public Employee Employee
{
get;
set;
}
}
}

View File

@ -0,0 +1,27 @@
@model MvcTagHelpersWebSite.Models.Warehouse
@addtaghelper "Microsoft.AspNet.Mvc.TagHelpers"
@{
ViewBag.Title = "Warehouse - Product";
}
<html>
<body>
@using (Html.BeginForm("CreateWarehouse", "MvcTagHelper_Home"))
{
<div>
<label asp-for="City" class="warehouse" />
<input asp-for="City" type="text" size="50" />
<span asp-validation-for="City" />
</div>
<div>
<label asp-for="Product" class="warehouse" />
<select asp-for="Product" asp-items="(IEnumerable<SelectListItem>)ViewBag.Items" />
<span asp-validation-for="Product" />
</div>
<div asp-validation-summary="All" class="warehouse" />
<input type="submit" />
}
</body>
</html>

View File

@ -0,0 +1,50 @@
@model MvcTagHelpersWebSite.Models.Warehouse
@addtaghelper "Microsoft.AspNet.Mvc.TagHelpers"
@{
ViewBag.Title = "Warehouse - Employee";
}
<html>
<body>
<form asp-controller="MvcTagHelper_Home" asp-action="EditWarehouse" asp-anti-forgery="false">
<div>
@Html.DisplayFor(m => m.City)
<input asp-for="City" type="text" />
</div>
<div>
<label>@Html.DisplayNameFor(m => m.Employee.Address)</label>
@Html.TextAreaFor(m => m.Employee.Address);
</div>
<div>
@Html.LabelFor(m => m.Employee.Password)
@Html.PasswordFor(m => m.Employee.Password)
</div>
<div>
<label>@Html.DisplayNameFor(m => m.Employee.PhoneNumber)</label>
@Html.TextBoxFor(m => m.Employee.PhoneNumber)
</div>
<div>
<label for="@Html.IdFor(m => m.Employee.Name)">@Html.NameFor(m => m.Employee.Name)</label>
<input asp-for="Employee.Name" type="text" />
@Html.ValidationMessageFor(m => m.Employee.Name)
</div>
<div>
@Html.LabelFor(m => m.Employee.Gender)
@Html.RadioButtonFor(m => m.Employee.Gender, "Female") Female
@Html.RadioButtonFor(m => m.Employee.Gender, "Male") Male
</div>
<div>
@Html.LabelFor(m => m.Employee.OfficeNumber)
@{
var offices = new SelectList(new string[] { "1001", "1002" });
}
@Html.DropDownListFor(m => m.Employee.OfficeNumber, offices)
</div>
@Html.HiddenFor(m => m.Employee.Number)
@Html.ValidationSummary()
<input type="submit" />
</form>
</body>
</html>

View File

@ -0,0 +1,35 @@
@model MvcTagHelpersWebSite.Models.Employee
@addtaghelper "Microsoft.AspNet.Mvc.TagHelpers"
<div>
@Html.LabelFor(m => m.Number)
@Html.TextBoxFor(m => m.Number, htmlAttributes: new { disabled = "disabled", @readonly= "readonly" })
<input asp-for="Number" type="number" class="form-control" />
</div>
<div>
<label asp-for="Name" class="employee" />
@Html.TextAreaFor(m => m.Name)
</div>
<div>
<label asp-for="PhoneNumber" class="employee" />
<input asp-for="PhoneNumber" type="tel" />
</div>
<div>
@{
var genders = new SelectList(new string[] { "Male", "Female" });
}
<label asp-for="Gender" class="employee" />
<select asp-for="Gender" asp-items="genders" />
</div>
<div>
<label asp-for="Remote" class="employee" />
@Html.CheckBoxFor(m=>m.Remote)
</div>
<div>
<label asp-for="OfficeNumber" class="employee" />
@{
var offices = new SelectList(new string[] {"1001","1002"});
}
@Html.DropDownListFor(m => m.OfficeNumber, offices)
</div>

View File

@ -0,0 +1,23 @@
@using MvcTagHelpersWebSite.Models
@model List<Employee>
@{
ViewBag.Title = "Employee Page";
}
<html>
<body>
@if (Model != null && Model.Count() != 0)
{
@using (@Html.BeginForm("EmployeeList", "MvcTagHelper_Home", FormMethod.Post))
{
@for (int i = 0; i < Model.Count; ++i)
{
@Html.EditorFor(m => m[i])
}
<input type="submit" />
}
}
</body>
</html>

View File

@ -0,0 +1,20 @@
@using MvcTagHelpersWebSite.Models
@model IEnumerable<Product>
@addtaghelper "Microsoft.AspNet.Mvc.TagHelpers"
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
@using (@Html.BeginForm("Index", "MvcTagHelper_Product", FormMethod.Post))
{
@foreach (var product in Model)
{
@await Html.PartialAsync("_ProductPartial", product)
}
<input type="submit" />
}
</body>
</html>

View File

@ -0,0 +1,20 @@
@model MvcTagHelpersWebSite.Models.Product
@addtaghelper "Microsoft.AspNet.Mvc.TagHelpers"
<div>
<label asp-for="HomePage" class="product" />
<input asp-for="HomePage" type="url" size="50" />
</div>
<div>
<label asp-for="Number" class="product" />
<input asp-for="Number" type="number"/>
</div>
<div>
<label asp-for="ProductName" class="product" />
<input asp-for="ProductName" type="text"/>
</div>
<div>
<label asp-for="Description" class="product" />
<textarea asp-for="Description" rows="4" cols="50" class="product" />
</div>