PartialTagHelper should not fallback to the current page's model if asp-for expression exists
Fixes #7295
This commit is contained in:
parent
a74ef9dfd9
commit
b30020a655
|
|
@ -101,7 +101,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
var view = viewEngineResult.View;
|
var view = viewEngineResult.View;
|
||||||
// Determine which ViewData we should use to construct a new ViewData
|
// Determine which ViewData we should use to construct a new ViewData
|
||||||
var baseViewData = ViewData ?? ViewContext.ViewData;
|
var baseViewData = ViewData ?? ViewContext.ViewData;
|
||||||
var model = For?.Model ?? ViewContext.ViewData.Model;
|
|
||||||
|
// Use the rendering View's model only if an asp-for expression does not exist
|
||||||
|
var model = For != null ? For.Model : ViewContext.ViewData.Model;
|
||||||
var newViewData = new ViewDataDictionary<object>(baseViewData, model);
|
var newViewData = new ViewDataDictionary<object>(baseViewData, model);
|
||||||
var partialViewContext = new ViewContext(ViewContext, view, newViewData, writer);
|
var partialViewContext = new ViewContext(ViewContext, view, newViewData, writer);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
// Testing InputTagHelpers invoked in the partial views
|
// Testing InputTagHelpers invoked in the partial views
|
||||||
{ "ProductList", "/HtmlGeneration_Product" },
|
{ "ProductList", "/HtmlGeneration_Product" },
|
||||||
{ "ProductListUsingTagHelpers", "/HtmlGeneration_Product" },
|
{ "ProductListUsingTagHelpers", "/HtmlGeneration_Product" },
|
||||||
|
{ "ProductListUsingTagHelpersWithNullModel", "/HtmlGeneration_Product" },
|
||||||
// Testing the ScriptTagHelper
|
// Testing the ScriptTagHelper
|
||||||
{ "Script", null },
|
{ "Script", null },
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form action="/HtmlGeneration_Product" method="post">
|
||||||
|
<div>
|
||||||
|
<label class="product" for="z0__HomePage">HomePage</label>
|
||||||
|
<input type="url" size="50" disabled="disabled" readonly="readonly" id="z0__HomePage" name="[0].HomePage" value="" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="product" for="z0__Number">Number</label>
|
||||||
|
<input type="number" data-val="true" data-val-required="The Number field is required." id="z0__Number" name="[0].Number" value="" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="product" for="z0__ProductName">ProductName</label>
|
||||||
|
<input type="text" data-val="true" data-val-required="The ProductName field is required." id="z0__ProductName" name="[0].ProductName" value="" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="product" for="z0__Description">Description</label>
|
||||||
|
<textarea rows="4" cols="50" class="product" id="z0__Description" name="[0].Description">
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>HtmlFieldPrefix = </div>
|
||||||
|
<input type="submit" />
|
||||||
|
<input name="__RequestVerificationToken" type="hidden" value="{0}" /></form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -233,6 +233,52 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
view.Verify();
|
view.Verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ProcessAsync_DoesNotUseModelFromViewdata_IfModelExpressionEvalulatesToNull()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var bufferScope = new TestViewBufferScope();
|
||||||
|
var partialName = "_Partial";
|
||||||
|
var modelMetadataProvider = new TestModelMetadataProvider();
|
||||||
|
var containerModel = new TestModel { Property = null };
|
||||||
|
var containerModelExplorer = modelMetadataProvider.GetModelExplorerForType(
|
||||||
|
typeof(TestModel),
|
||||||
|
containerModel);
|
||||||
|
var propertyModelExplorer = containerModelExplorer.GetExplorerForProperty(nameof(TestModel.Property));
|
||||||
|
|
||||||
|
var modelExpression = new ModelExpression("Property", propertyModelExplorer);
|
||||||
|
var viewContext = GetViewContext();
|
||||||
|
viewContext.ViewData.Model = new object();
|
||||||
|
|
||||||
|
var view = new Mock<IView>();
|
||||||
|
view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
|
||||||
|
.Callback((ViewContext v) =>
|
||||||
|
{
|
||||||
|
Assert.Null(v.ViewData.Model);
|
||||||
|
})
|
||||||
|
.Returns(Task.CompletedTask)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
var viewEngine = new Mock<ICompositeViewEngine>();
|
||||||
|
viewEngine.Setup(v => v.GetView(It.IsAny<string>(), partialName, false))
|
||||||
|
.Returns(ViewEngineResult.Found(partialName, view.Object));
|
||||||
|
|
||||||
|
var tagHelper = new PartialTagHelper(viewEngine.Object, bufferScope)
|
||||||
|
{
|
||||||
|
Name = partialName,
|
||||||
|
ViewContext = viewContext,
|
||||||
|
For = modelExpression,
|
||||||
|
};
|
||||||
|
var tagHelperContext = GetTagHelperContext();
|
||||||
|
var output = GetTagHelperOutput();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await tagHelper.ProcessAsync(tagHelperContext, output);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
view.Verify();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ProcessAsync_SetsHtmlFieldPrefix_UsingModelExpression()
|
public async Task ProcessAsync_SetsHtmlFieldPrefix_UsingModelExpression()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,16 @@ namespace HtmlGenerationWebSite.Controllers
|
||||||
|
|
||||||
public IActionResult ProductListUsingTagHelpers() => View(_products);
|
public IActionResult ProductListUsingTagHelpers() => View(_products);
|
||||||
|
|
||||||
|
public IActionResult ProductListUsingTagHelpersWithNullModel()
|
||||||
|
{
|
||||||
|
var model = new List<Product>
|
||||||
|
{
|
||||||
|
null,
|
||||||
|
};
|
||||||
|
|
||||||
|
return View(nameof(ProductListUsingTagHelpers), model);
|
||||||
|
}
|
||||||
|
|
||||||
public IActionResult EmployeeList()
|
public IActionResult EmployeeList()
|
||||||
{
|
{
|
||||||
var employees = new List<Employee>
|
var employees = new List<Employee>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue