Add another view to MvcTagHelpersWebSite using HTML helpers

- with some `<text>` hacks, generated HTML is almost identical to tag helper version
 - attribute order (HTML helpers consistently order alphabetically) is primary difference
- bit more testing, therefore related to #453

nits:
- remove some trailing whitespace
- clean up style in `MvcTagHelperTest[s]` and `MvcTagHelper_HomeController`
 - e.g. more init syntax, fewer duplicate variables
- correct "MvcTagHelperTest~~s~~" file / class name
- remove unused `Order.OrderNumber` property in MvcTagHelpersWebSite project
- correct one spelling mistake
This commit is contained in:
Doug Bunting 2015-01-19 15:14:01 -08:00
parent df0d556fcc
commit bf00f478e5
7 changed files with 232 additions and 67 deletions

View File

@ -0,0 +1,76 @@

<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<form action="/MvcTagHelper_Order/Submit" method="post">
<div>
<label class="order" for="Shipping">Shipping</label>
<input id="Shipping" name="Shipping" size="50" type="text" value="Your shipping method is UPSP" />
</div>
<div>
<label class="order" for="ShippingDateTime">ShippingDateTime</label>
<input id="ShippingDateTime" name="ShippingDateTime" type="datetime-local" value="01/01/0001 00:00:00" />
</div>
<div>
<label class="order" for="Products">Products</label>
<select id="Products" multiple="multiple" 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>
<label class="order" for="OrderDate">OrderDate</label>
<input id="OrderDate" name="OrderDate" type="datetime" value="0001/01/01/ A.D." />
</div>
<div>
<label class="order" for="NeedSpecialHandle">NeedSpecialHandle</label>
<input checked="checked" id="NeedSpecialHandle" name="NeedSpecialHandle" type="checkbox" value="true" /><input name="NeedSpecialHandle" type="hidden" value="false" />
</div>
<div>
<label class="order" for="PaymentMethod">PaymentMethod</label>
<select id="PaymentMethod" multiple="multiple" name="PaymentMethod"><option value="Credit">Credit</option>
<option selected="selected" value="Check">Check</option>
</select>
</div>
<div>
<label class="order" for="Customer_Number">Number</label>
<input class="form-control" 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="Customer_Number" name="Customer.Number" type="number" value="1" />
<span class="field-validation-valid" data-valmsg-for="Customer.Number" data-valmsg-replace="true"></span>
</div>
<div>
<label class="order" for="Customer_Name">Name</label>
<input id="Customer_Name" name="Customer.Name" type="text" value="NameStringValue" />
</div>
<div>
<label class="order" for="Customer_Email">Email</label>
<input id="Customer_Email" name="Customer.Email" type="email" value="" />
<span class="field-validation-valid" data-valmsg-for="Customer.Email" data-valmsg-replace="true"></span>
</div>
<div>
<label class="order" for="Customer_PhoneNumber">PhoneNumber</label>
<input id="Customer_PhoneNumber" name="Customer.PhoneNumber" type="tel" value="" />
</div>
<div>
<label class="order" for="Customer_Password">Password</label>
<input class="form-control" data-val="true" data-val-required="The Password field is required." id="Customer_Password" name="Customer.Password" type="password" />
<span class="field-validation-valid" data-valmsg-for="Customer.Password" data-valmsg-replace="true"></span>
</div>
<div>
<label class="order" for="Customer_Gender">Gender</label>
<input id="Customer_Gender" name="Customer.Gender" type="radio" value="Male" /> Male
<input checked="checked" id="Customer_Gender" name="Customer.Gender" type="radio" value="Female" /> Female
<span class="field-validation-valid" data-valmsg-for="Customer.Gender" data-valmsg-replace="true"></span>
</div>
<div class="validation-summary-valid order" data-valmsg-summary="true"><ul><li style="display:none"></li>
</ul></div>
<input id="Customer_Key" name="Customer.Key" type="hidden" value="KeyA" />
<input type="submit"></input>
<input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
</body>
</html>

View File

@ -54,7 +54,7 @@
<div>
<label class="product" for="z2__Description">Description</label>
<textarea rows="4" cols="50" class="product" id="z2__Description" name="[2].Description">
Product_2 desription</textarea>
Product_2 description</textarea>
</div> <input type="submit"></input>
</form></body>
</html>

View File

@ -15,23 +15,26 @@ using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
{
public class MvcTagHelpersTests
public class MvcTagHelpersTest
{
private readonly IServiceProvider _provider = TestHelper.CreateServices("MvcTagHelpersWebSite");
private readonly Action<IApplicationBuilder> _app = new Startup().Configure;
private static readonly Assembly _resourcesAssembly = typeof(MvcTagHelpersTests).GetTypeInfo().Assembly;
private static readonly Assembly _resourcesAssembly = typeof(MvcTagHelpersTest).GetTypeInfo().Assembly;
[Theory]
[InlineData("Index", null)]
// Test ability to generate nearly identical HTML with MVC tag and HTML helpers.
// Only attribute order should differ.
[InlineData("Order", "/MvcTagHelper_Order/Submit")]
[InlineData("OrderUsingHtmlHelpers", "/MvcTagHelper_Order/Submit")]
[InlineData("Product", null)]
[InlineData("Customer", "/Customer/MvcTagHelper_Customer")]
// Testing InputTagHelpers invoked in the partial views
[InlineData("ProductList", null)]
// 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)]
[InlineData("EmployeeList", null)]
// Testing SelectTagHelper with Html.BeginForm
[InlineData("CreateWarehouse", null)]
// Testing the HTML helpers with FormTagHelper
[InlineData("EditWarehouse", null)]
// Testing the EnvironmentTagHelper
@ -45,9 +48,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// The K runtime compiles every file under compiler/resources as a resource at runtime with the same name
// as the file name, in order to update a baseline you just need to change the file in that folder.
var expectedContent =
await _resourcesAssembly.ReadResourceAsStringAsync
("compiler/resources/MvcTagHelpersWebSite.MvcTagHelper_Home." + action + ".html");
var expectedContent = await _resourcesAssembly.ReadResourceAsStringAsync(
"compiler/resources/MvcTagHelpersWebSite.MvcTagHelper_Home." + action + ".html");
// Act
// The host is not important as everything runs in memory and tests are isolated from each other.
@ -72,9 +74,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
var expectedContent =
await _resourcesAssembly.ReadResourceAsStringAsync
("compiler/resources/MvcTagHelpersWebSite.MvcTagHelper_Customer.Index.html");
var expectedContent = await _resourcesAssembly.ReadResourceAsStringAsync(
"compiler/resources/MvcTagHelpersWebSite.MvcTagHelper_Customer.Index.html");
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Customer/MvcTagHelper_Customer");
var nameValueCollection = new List<KeyValuePair<string, string>>

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using MvcTagHelpersWebSite.Models;
@ -12,48 +11,60 @@ namespace MvcTagHelpersWebSite.Controllers
{
public class MvcTagHelper_HomeController : Controller
{
private readonly List<Product> _products = new List<Product>();
public MvcTagHelper_HomeController()
private readonly List<Product> _products = new List<Product>
{
_products.Add(new Product
new Product
{
ProductName = "Product_0",
Number = 0,
HomePage = new Uri("http://www.contoso.com")
});
_products.Add(new Product
},
new Product
{
ProductName = "Product_1",
Number = 1,
});
_products.Add(new Product
},
new Product
{
ProductName = "Product_2",
Number = 2,
Description = "Product_2 desription"
});
Description = "Product_2 description"
},
};
private readonly IEnumerable<SelectListItem> _productsList;
private readonly IEnumerable<SelectListItem> _productsListWithSelection;
private readonly Order _order = new Order
{
Shipping = "UPSP",
Customer = new Customer
{
Key = "KeyA",
Number = 1,
Gender = Gender.Female,
Name = "NameStringValue",
},
NeedSpecialHandle = true,
PaymentMethod = new List<string> { "Check" },
};
public MvcTagHelper_HomeController()
{
_productsList = new SelectList(_products, "Number", "ProductName");
_productsListWithSelection = new SelectList(_products, "Number", "ProductName", 2);
}
public IActionResult Order()
{
ViewBag.Items = new SelectList(_products, "Number", "ProductName", 2);
ViewBag.Items = _productsListWithSelection;
var order = new Order
{
Shipping = "UPSP",
Customer = new Customer
{
Key = "KeyA",
Number = 1,
Gender = Gender.Female,
Name = "NameStringValue",
},
NeedSpecialHandle = true,
PaymentMethod = new List<string> { "Check" }
};
return View(_order);
}
return View(order);
public IActionResult OrderUsingHtmlHelpers()
{
ViewBag.Items = _productsListWithSelection;
return View(_order);
}
public IActionResult Product()
@ -63,6 +74,7 @@ namespace MvcTagHelpersWebSite.Controllers
HomePage = new System.Uri("http://www.contoso.com"),
Description = "Type the product description"
};
return View(product);
}
@ -88,34 +100,35 @@ namespace MvcTagHelpersWebSite.Controllers
public IActionResult EmployeeList()
{
var employees = new List<Employee>();
employees.Add(new Employee
var employees = new List<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
});
new Employee
{
Name = "EmployeeName_0",
Number = 0,
Address = "Employee_0 address"
},
new Employee
{
Name = "EmployeeName_1",
Number = 1,
OfficeNumber = "1002",
Gender = Gender.Female
},
new Employee
{
Name = "EmployeeName_2",
Number = 2,
Remote = true
},
};
return View(employees);
}
public IActionResult CreateWarehouse()
{
ViewBag.Items = new SelectList(_products, "Number", "ProductName", 9);
ViewBag.Items = _productsList;
return View();
}
@ -134,6 +147,7 @@ namespace MvcTagHelpersWebSite.Controllers
Gender = Gender.Female
}
};
return View(warehouse);
}

View File

@ -14,12 +14,6 @@ namespace MvcTagHelpersWebSite.Models
set;
}
public int OrderNumber
{
get;
set;
}
public DateTimeOffset OrderDate
{
get;

View File

@ -0,0 +1,4 @@
@using MvcTagHelpersWebSite.Models
@model Gender
@Html.RadioButtonFor(m => m, value: "Male") Male
@Html.RadioButtonFor(m => m, value: "Female") Female

View File

@ -0,0 +1,76 @@
@model MvcTagHelpersWebSite.Models.Order
@{
ViewBag.Title = "Order Page";
}
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
@* Use comments and <text/> elements to force whitespace in generated HTML. *@@using (
Html.BeginForm(actionName: "Submit", controllerName: "MvcTagHelper_Order"))
{<text></text>
<div>
@Html.LabelFor(m => m.Shipping, htmlAttributes: new { @class = "order" })
@Html.TextBoxFor(m => m.Shipping, format: "Your shipping method is {0}", htmlAttributes: new { size = "50" })
</div>
<div>
@Html.LabelFor(m => m.ShippingDateTime, htmlAttributes: new { @class = "order" })
@Html.TextBoxFor(m => m.ShippingDateTime, htmlAttributes: new { type = "datetime-local" })
</div>
<div>
@Html.LabelFor(m => m.Products, htmlAttributes: new { @class = "order" })
@{ var productSelectList = (IEnumerable<SelectListItem>)ViewBag.Items; }
@Html.ListBoxFor(m => m.Products, productSelectList)
</div>
<div>
@Html.LabelFor(m => m.OrderDate, htmlAttributes: new { @class = "order" })
@Html.TextBoxFor(m => m.OrderDate, format: "{0:yyyy/MM/dd/ g}", htmlAttributes: new { type = "datetime" })
</div>
<div>
@Html.LabelFor(m => m.NeedSpecialHandle, htmlAttributes: new { @class = "order" })
@Html.CheckBoxFor(m => m.NeedSpecialHandle)
</div>
<div>
@Html.LabelFor(m => m.PaymentMethod, htmlAttributes: new { @class = "order" })
@Html.ListBoxFor(m => m.PaymentMethod, selectList: new SelectList(new[] { new { value = "Credit" }, new { value = "Check" } }, dataValueField: "value", dataTextField: "value"))
</div>
<div>
@Html.LabelFor(m => m.Customer.Number, htmlAttributes: new { @class = "order" })
@Html.TextBoxFor(m => m.Customer.Number, htmlAttributes: new { type = "number", @class = "form-control" })
@Html.ValidationMessageFor(m => m.Customer.Number)
</div>
<div>
@Html.LabelFor(m => m.Customer.Name, htmlAttributes: new { @class = "order" })
@Html.TextBoxFor(m => m.Customer.Name)
</div>
<div>
@Html.LabelFor(m => m.Customer.Email, htmlAttributes: new { @class = "order" })
@Html.TextBoxFor(m => m.Customer.Email, htmlAttributes: new { type = "email" })
@Html.ValidationMessageFor(m => m.Customer.Email)
</div>
<div>
@Html.LabelFor(m => m.Customer.PhoneNumber, htmlAttributes: new { @class = "order" })
@Html.TextBoxFor(m => m.Customer.PhoneNumber, htmlAttributes: new { type = "tel" })
</div>
<div>
@Html.LabelFor(m => m.Customer.Password, htmlAttributes: new { @class = "order" })
@Html.PasswordFor(m => m.Customer.Password, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Customer.Password)
</div>
<div>
@Html.LabelFor(m => m.Customer.Gender, htmlAttributes: new { @class = "order" })
@Html.EditorFor(model => model.Customer.Gender, templateName: "GenderUsingHtmlHelpers")
@Html.ValidationMessageFor(m => m.Customer.Gender)
</div><text>
</text>@Html.ValidationSummary(message: null, htmlAttributes: new { @class = "order" })<text>
</text>@Html.HiddenFor(m => m.Customer.Key)<text></text>
<input type="submit"></input><text>
</text>@Html.AntiForgeryToken();
}@**@
</body>
</html>