diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs index ff4aefaebe..07efd3fbcc 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorView.cs @@ -88,12 +88,8 @@ namespace Microsoft.AspNet.Mvc.Razor private async Task RenderPageCoreAsync(IRazorPage page, ViewContext context) { - // Activating a page might mutate the ViewContext (for instance ViewContext.ViewData) is mutated by - // RazorPageActivator. We'll instead pass in a copy of the ViewContext. - var pageViewContext = new ViewContext(context, context.View, context.ViewData, context.Writer); - page.ViewContext = pageViewContext; - _pageActivator.Activate(page, pageViewContext); - + page.ViewContext = context; + _pageActivator.Activate(page, context); await page.ExecuteAsync(); } diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/ViewEngineTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/ViewEngineTests.cs index 266ac264c2..7ddfc61dad 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/ViewEngineTests.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/ViewEngineTests.cs @@ -85,5 +85,24 @@ test-value"; var body = await result.HttpContext.Response.ReadBodyAsStringAsync(); Assert.Equal(expected, body.Trim()); } + + [Fact] + public async Task RazorView_PassesViewContextBetweenViewAndLayout() + { + var expected = +@"Page title + +partial-content +component-content"; + var server = TestServer.Create(_provider, _app); + var client = server.Handler; + + // Act + var result = await client.GetAsync("http://localhost/ViewEngine/ViewPassesViewDataToLayout"); + + // Assert + var body = await result.HttpContext.Response.ReadBodyAsStringAsync(); + Assert.Equal(expected, body.Trim()); + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewTest.cs index e2ec6a95a6..686d9affee 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorViewTest.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Mvc.Razor } [Fact] - public async Task RenderAsync_WithoutHierarchy_ActivatesViews_WithACopyOfViewContext() + public async Task RenderAsync_WithoutHierarchy_ActivatesViews_WithThePassedInViewContext() { // Arrange var viewData = new ViewDataDictionary(Mock.Of()); @@ -59,12 +59,11 @@ namespace Microsoft.AspNet.Mvc.Razor page, executeViewHierarchy: false); var viewContext = CreateViewContext(view); - var expectedViewData = viewContext.ViewData; var expectedWriter = viewContext.Writer; activator.Setup(a => a.Activate(page, It.IsAny())) .Callback((IRazorPage p, ViewContext c) => { - Assert.NotSame(c, viewContext); + Assert.Same(c, viewContext); c.ViewData = viewData; }) .Verifiable(); @@ -74,7 +73,6 @@ namespace Microsoft.AspNet.Mvc.Razor // Assert activator.Verify(); - Assert.Same(expectedViewData, viewContext.ViewData); Assert.Same(expectedWriter, viewContext.Writer); } diff --git a/test/WebSites/RazorWebSite/Components/ComponentThatSetsTitle.cs b/test/WebSites/RazorWebSite/Components/ComponentThatSetsTitle.cs new file mode 100644 index 0000000000..5e3994aff0 --- /dev/null +++ b/test/WebSites/RazorWebSite/Components/ComponentThatSetsTitle.cs @@ -0,0 +1,16 @@ +// 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 Microsoft.AspNet.Mvc; + +namespace MvcSample.Web.Components +{ + [ViewComponent(Name = "ComponentThatSetsTitle")] + public class ComponentThatSetsTitle : ViewComponent + { + public IViewComponentResult Invoke() + { + return View(); + } + } +} \ No newline at end of file diff --git a/test/WebSites/RazorWebSite/Controllers/ViewEngineController.cs b/test/WebSites/RazorWebSite/Controllers/ViewEngineController.cs index ffb93d978f..29a10087bd 100644 --- a/test/WebSites/RazorWebSite/Controllers/ViewEngineController.cs +++ b/test/WebSites/RazorWebSite/Controllers/ViewEngineController.cs @@ -36,5 +36,11 @@ namespace RazorWebSite.Controllers }; return View(model); } + + public ViewResult ViewPassesViewDataToLayout() + { + ViewData["Title"] = "Controller title"; + return View("ViewWithTitle"); + } } } \ No newline at end of file diff --git a/test/WebSites/RazorWebSite/RazorWebSite.kproj b/test/WebSites/RazorWebSite/RazorWebSite.kproj index 272be37cd7..1bbeeed525 100644 --- a/test/WebSites/RazorWebSite/RazorWebSite.kproj +++ b/test/WebSites/RazorWebSite/RazorWebSite.kproj @@ -24,7 +24,11 @@ + + + + @@ -34,6 +38,7 @@ + diff --git a/test/WebSites/RazorWebSite/Views/Shared/Components/ComponentThatSetsTitle/Default.cshtml b/test/WebSites/RazorWebSite/Views/Shared/Components/ComponentThatSetsTitle/Default.cshtml new file mode 100644 index 0000000000..053441629e --- /dev/null +++ b/test/WebSites/RazorWebSite/Views/Shared/Components/ComponentThatSetsTitle/Default.cshtml @@ -0,0 +1,4 @@ +@{ + ViewData["Title"] = "Component title"; +} +component-content \ No newline at end of file diff --git a/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithTitle.cshtml b/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithTitle.cshtml new file mode 100644 index 0000000000..aac3b8a1ee --- /dev/null +++ b/test/WebSites/RazorWebSite/Views/Shared/_LayoutWithTitle.cshtml @@ -0,0 +1,2 @@ +@ViewBag.Title +@RenderBody() \ No newline at end of file diff --git a/test/WebSites/RazorWebSite/Views/Shared/_PartialThatSetsTitle.cshtml b/test/WebSites/RazorWebSite/Views/Shared/_PartialThatSetsTitle.cshtml new file mode 100644 index 0000000000..a5bf32c08d --- /dev/null +++ b/test/WebSites/RazorWebSite/Views/Shared/_PartialThatSetsTitle.cshtml @@ -0,0 +1,4 @@ +@{ + ViewBag.Title = "Partial title"; +} +partial-content \ No newline at end of file diff --git a/test/WebSites/RazorWebSite/Views/ViewEngine/ViewWithTitle.cshtml b/test/WebSites/RazorWebSite/Views/ViewEngine/ViewWithTitle.cshtml new file mode 100644 index 0000000000..d6e997ffd9 --- /dev/null +++ b/test/WebSites/RazorWebSite/Views/ViewEngine/ViewWithTitle.cshtml @@ -0,0 +1,7 @@ +@{ + ViewData["Title"] = "Page title"; + // The invoked partial sets a title, but this shouldn't override the current page's ViewData \ ViewBag. + await Html.RenderPartialAsync("_PartialThatSetsTitle"); + await Component.RenderInvokeAsync("ComponentThatSetsTitle"); + Layout = "/Views/Shared/_LayoutWithTitle.cshtml"; +} \ No newline at end of file