From d2fe1ebad763c948ecc47612d01c26a7eff9a1f6 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Thu, 15 Jan 2015 16:14:30 -0800 Subject: [PATCH] Allow `@Model` in bound tag helper attribute value - part II of #1253 - an expected case in template .cshtml files - expression has name `""`; led to `ArgumentException` in `ModelExpression` - test `@Model` and `@model.Property` in unit and functional tests - update baselines to match nits: - remove a few unecessary `@`s in .cshtml files - correct field names & ids in ProductList.cshtml (`foreach` confuses MVC) - led to correct valiation attributes as well --- .../Rendering/ModelExpression.cs | 7 +- ...elpersWebSite.MvcTagHelper_Home.Order.html | 2 +- ...WebSite.MvcTagHelper_Home.ProductList.html | 70 +++++++++---------- .../MvcRazorHostTest.cs | 10 ++- .../Input/ModelExpressionTagHelper.cshtml | 3 +- .../DesignTime/ModelExpressionTagHelper.cs | 6 ++ .../Runtime/ModelExpressionTagHelper.cs | 18 ++++- .../SelectTagHelperTest.cs | 12 ++-- .../EditorTemplates/Gender.cshtml | 5 ++ .../MvcTagHelper_Home/EmployeeList.cshtml | 4 +- .../Views/MvcTagHelper_Home/Order.cshtml | 3 +- .../MvcTagHelper_Home/ProductList.cshtml | 13 +++- .../MvcTagHelper_Home/_ProductPartial.cshtml | 4 -- 13 files changed, 96 insertions(+), 61 deletions(-) create mode 100644 test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/EditorTemplates/Gender.cshtml diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/ModelExpression.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/ModelExpression.cs index d5179f5f93..9676011734 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Rendering/ModelExpression.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/ModelExpression.cs @@ -21,13 +21,8 @@ namespace Microsoft.AspNet.Mvc.Rendering /// /// Metadata about the of interest. /// - public ModelExpression(string name, [NotNull] ModelMetadata metadata) + public ModelExpression([NotNull] string name, [NotNull] ModelMetadata metadata) { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(name)); - } - Name = name; Metadata = metadata; } diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Order.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Order.html index 97c41f37b0..a9e3d25b38 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Order.html +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.Order.html @@ -65,7 +65,7 @@
Male - Female + Female
  • diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.ProductList.html b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.ProductList.html index 80913b1e19..d71b0100a0 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.ProductList.html +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/Compiler/Resources/MvcTagHelpersWebSite.MvcTagHelper_Home.ProductList.html @@ -4,56 +4,56 @@ -
    +
    + + +
    +
    - - + +
    - - + +
    - - -
    -
    - - +
    + + +
    + +
    + +
    - - + +
    - - -
    -
    - - -
    -
    - - +
    + + +
    + +
    + +
    - - + +
    - - -
    -
    - - -
    -
    - -
    diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/MvcRazorHostTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/MvcRazorHostTest.cs index 9f86c9362c..9b17b11561 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/MvcRazorHostTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/MvcRazorHostTest.cs @@ -58,7 +58,15 @@ namespace Microsoft.AspNet.Mvc.Razor generatedAbsoluteIndex: 2105, generatedLineIndex: 53, generatedCharacterIndex: 95, - contentLength: 3) + contentLength: 3), + BuildLineMapping( + documentAbsoluteIndex: 166, + documentLineIndex: 5, + documentCharacterIndex: 18, + generatedAbsoluteIndex: 2418, + generatedLineIndex: 59, + generatedCharacterIndex: 87, + contentLength: 5), }; // Act and Assert diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Input/ModelExpressionTagHelper.cshtml b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Input/ModelExpressionTagHelper.cshtml index 73751bc204..a12b9f1b41 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Input/ModelExpressionTagHelper.cshtml +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Input/ModelExpressionTagHelper.cshtml @@ -2,4 +2,5 @@ @addtaghelper "Microsoft.AspNet.Mvc.Razor.InputTestTagHelper, Microsoft.AspNet.Mvc.Razor.Host.Test" - \ No newline at end of file + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/DesignTime/ModelExpressionTagHelper.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/DesignTime/ModelExpressionTagHelper.cs index 91c93af0d2..2aaeef120b 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/DesignTime/ModelExpressionTagHelper.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/DesignTime/ModelExpressionTagHelper.cs @@ -53,6 +53,12 @@ #line 5 "TestFiles/Input/ModelExpressionTagHelper.cshtml" __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__model => __model.Now); +#line default +#line hidden + __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper = CreateTagHelper(); +#line 6 "TestFiles/Input/ModelExpressionTagHelper.cshtml" +__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__model => Model); + #line default #line hidden } diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Runtime/ModelExpressionTagHelper.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Runtime/ModelExpressionTagHelper.cs index b71325c6c3..c0bfc2df2f 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Runtime/ModelExpressionTagHelper.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Runtime/ModelExpressionTagHelper.cs @@ -1,4 +1,4 @@ -#pragma checksum "TestFiles/Input/ModelExpressionTagHelper.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "5de24be79bca2d0ce7e180eab7b197442352f137" +#pragma checksum "TestFiles/Input/ModelExpressionTagHelper.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "f068e0ad45f53d090f04213f542f87fb2cf750d2" namespace Asp { using Microsoft.AspNet.Razor.Runtime.TagHelpers; @@ -51,6 +51,22 @@ namespace Asp #line 5 "TestFiles/Input/ModelExpressionTagHelper.cshtml" __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__model => __model.Now); +#line default +#line hidden + __tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For); + __tagHelperExecutionContext.Output = __tagHelperRunner.RunAsync(__tagHelperExecutionContext).Result; + WriteLiteral(__tagHelperExecutionContext.Output.GenerateStartTag()); + WriteLiteral(__tagHelperExecutionContext.Output.GenerateEndTag()); + __tagHelperExecutionContext = __tagHelperScopeManager.End(); + BeginContext(146, 2, true); + WriteLiteral("\r\n"); + EndContext(); + __tagHelperExecutionContext = __tagHelperScopeManager.Begin("input-test", "test"); + __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper = CreateTagHelper(); + __tagHelperExecutionContext.Add(__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper); +#line 6 "TestFiles/Input/ModelExpressionTagHelper.cshtml" +__Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For = CreateModelExpression(__model => Model); + #line default #line hidden __tagHelperExecutionContext.AddTagHelperAttribute("for", __Microsoft_AspNet_Mvc_Razor_InputTestTagHelper.For); diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs index 9793d7c088..07b90efa4e 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/SelectTagHelperTest.cs @@ -315,24 +315,24 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var tagHelperContext = new TagHelperContext(contextAttributes, uniqueId: "test"); var output = new TagHelperOutput(expectedTagName, originalAttributes, content); - // TODO: https://github.com/aspnet/Mvc/issues/1253 - // In real (model => model) scenario, ModelExpression should have name "" and - // TemplateInfo.HtmlFieldPrefix should be "Property1" but empty ModelExpression name is not currently - // supported, see also #1408. var metadataProvider = new EmptyModelMetadataProvider(); string model = null; var metadata = metadataProvider.GetMetadataForType(() => model, typeof(string)); - var modelExpression = new ModelExpression(propertyName, metadata); var htmlGenerator = new Mock(MockBehavior.Strict); var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator.Object, metadataProvider); + + // Simulate a (model => model) scenario. E.g. the calling helper may appear in a low-level template. + var modelExpression = new ModelExpression(string.Empty, metadata); + viewContext.ViewData.TemplateInfo.HtmlFieldPrefix = propertyName; + ICollection selectedValues = new string[0]; htmlGenerator .Setup(real => real.GenerateSelect( viewContext, metadata, null, // optionLabel - propertyName, // name + string.Empty, // name expectedItems, expectedAllowMultiple, null, // htmlAttributes diff --git a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/EditorTemplates/Gender.cshtml b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/EditorTemplates/Gender.cshtml new file mode 100644 index 0000000000..1481c6c16f --- /dev/null +++ b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/EditorTemplates/Gender.cshtml @@ -0,0 +1,5 @@ +@using MvcTagHelpersWebSite.Models +@model Gender +@addtaghelper "Microsoft.AspNet.Mvc.TagHelpers" + Male + Female \ No newline at end of file diff --git a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/EmployeeList.cshtml b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/EmployeeList.cshtml index e2c76b0487..173c1dbe39 100644 --- a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/EmployeeList.cshtml +++ b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/EmployeeList.cshtml @@ -10,9 +10,9 @@ @if (Model != null && Model.Count() != 0) { - @using (@Html.BeginForm("EmployeeList", "MvcTagHelper_Home", FormMethod.Post)) + using (@Html.BeginForm("EmployeeList", "MvcTagHelper_Home", FormMethod.Post)) { - @for (int i = 0; i < Model.Count; ++i) + for (int i = 0; i < Model.Count; ++i) { @Html.EditorFor(m => m[i]) } diff --git a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/Order.cshtml b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/Order.cshtml index 1bac052993..703213b130 100644 --- a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/Order.cshtml +++ b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/Order.cshtml @@ -72,8 +72,7 @@
diff --git a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/ProductList.cshtml b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/ProductList.cshtml index 49543dcd0f..7c2889c7a8 100644 --- a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/ProductList.cshtml +++ b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/ProductList.cshtml @@ -10,9 +10,18 @@ @using (@Html.BeginForm("Index", "MvcTagHelper_Product", FormMethod.Post)) { - @foreach (var product in Model) + var index = 0; + var fieldPrefix = ViewData.TemplateInfo.HtmlFieldPrefix; + foreach (var model in Model) { - @await Html.PartialAsync("_ProductPartial", product) + @* Update HtmlFieldPrefix so generated for, id and name attribute values are correct. *@ + ViewData.TemplateInfo.HtmlFieldPrefix = fieldPrefix + string.Format("[{0}]", index++); +
+
+ @await Html.PartialAsync("_ProductPartial", model) + ViewData.TemplateInfo.HtmlFieldPrefix = fieldPrefix; } } diff --git a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/_ProductPartial.cshtml b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/_ProductPartial.cshtml index 2f658947eb..dcdf146564 100644 --- a/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/_ProductPartial.cshtml +++ b/test/WebSites/MvcTagHelpersWebSite/Views/MvcTagHelper_Home/_ProductPartial.cshtml @@ -2,10 +2,6 @@ @addtaghelper "Microsoft.AspNet.Mvc.TagHelpers" -
-