diff --git a/src/Mvc/Mvc.RazorPages/ref/Microsoft.AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs b/src/Mvc/Mvc.RazorPages/ref/Microsoft.AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs index 4043d5eded..e8959d832a 100644 --- a/src/Mvc/Mvc.RazorPages/ref/Microsoft.AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs +++ b/src/Mvc/Mvc.RazorPages/ref/Microsoft.AspNetCore.Mvc.RazorPages.netcoreapp3.0.cs @@ -368,6 +368,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages { protected PageBase() { } public Microsoft.AspNetCore.Http.HttpContext HttpContext { get { throw null; } } + public Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider MetadataProvider { get { throw null; } set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary ModelState { get { throw null; } } public Microsoft.AspNetCore.Mvc.RazorPages.PageContext PageContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public Microsoft.AspNetCore.Http.HttpRequest Request { get { throw null; } } @@ -500,6 +501,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages { protected PageModel() { } public Microsoft.AspNetCore.Http.HttpContext HttpContext { get { throw null; } } + public Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider MetadataProvider { get { throw null; } set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary ModelState { get { throw null; } } [Microsoft.AspNetCore.Mvc.RazorPages.PageContextAttribute] public Microsoft.AspNetCore.Mvc.RazorPages.PageContext PageContext { get { throw null; } set { } } diff --git a/src/Mvc/Mvc.RazorPages/src/PageBase.cs b/src/Mvc/Mvc.RazorPages/src/PageBase.cs index 0ae4993b35..32f6810281 100644 --- a/src/Mvc/Mvc.RazorPages/src/PageBase.cs +++ b/src/Mvc/Mvc.RazorPages/src/PageBase.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Net.Http.Headers; @@ -61,6 +62,19 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// public ModelStateDictionary ModelState => PageContext?.ModelState; + /// + /// Gets or sets the . + /// + public IModelMetadataProvider MetadataProvider + { + get + { + _metadataProvider ??= HttpContext?.RequestServices?.GetRequiredService(); + return _metadataProvider; + } + set => _metadataProvider = value ?? throw new ArgumentNullException(nameof(value)); + } + private IObjectModelValidator ObjectValidator { get @@ -74,19 +88,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } } - private IModelMetadataProvider MetadataProvider - { - get - { - if (_metadataProvider == null) - { - _metadataProvider = HttpContext?.RequestServices?.GetRequiredService(); - } - - return _metadataProvider; - } - } - private IModelBinderFactory ModelBinderFactory { get @@ -216,7 +217,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => Content(content, (MediaTypeHeaderValue)null); /// - /// Creates a object with by specifying a + /// Creates a object with by specifying a /// string and a content type. /// /// The content to write to the response. @@ -226,7 +227,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => Content(content, MediaTypeHeaderValue.Parse(contentType)); /// - /// Creates a object with by specifying a + /// Creates a object with by specifying a /// string, a , and . /// /// The content to write to the response. @@ -245,7 +246,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Creates a object with by specifying a + /// Creates a object with by specifying a /// string and a . /// /// The content to write to the response. @@ -292,14 +293,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// challenge. /// The created for the response. /// - /// Some authentication schemes, such as cookies, will convert to + /// Some authentication schemes, such as cookies, will convert to /// a redirect to show a login page. /// public virtual ForbidResult Forbid(AuthenticationProperties properties) => new ForbidResult(properties); /// - /// Creates a ( by default) with the + /// Creates a ( by default) with the /// specified authentication schemes and . /// /// used to perform the authentication @@ -405,7 +406,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => new PhysicalFileResult(physicalPath, contentType) { FileDownloadName = fileDownloadName }; /// - /// Creates a object that redirects + /// Creates a object that redirects /// () to the specified local . /// /// The local URL to redirect to. @@ -438,7 +439,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Creates a object with set to - /// false and set to true + /// false and set to true /// () using the specified . /// /// The local URL to redirect to. @@ -455,7 +456,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Creates a object with set to - /// true and set to true + /// true and set to true /// () using the specified . /// /// The local URL to redirect to. @@ -527,7 +528,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Creates a object with set to false - /// and set to true () + /// and set to true () /// using the specified . /// /// The URL to redirect to. @@ -544,7 +545,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Creates a object with set to true - /// and set to true () + /// and set to true () /// using the specified . /// /// The URL to redirect to. @@ -568,7 +569,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToAction(actionName, routeValues: null); /// - /// Redirects () to the specified action using the + /// Redirects () to the specified action using the /// and . /// /// The name of the action. @@ -578,7 +579,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToAction(actionName, controllerName: null, routeValues: routeValues); /// - /// Redirects () to the specified action using the + /// Redirects () to the specified action using the /// and the . /// /// The name of the action. @@ -632,15 +633,15 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => new RedirectToActionResult(actionName, controllerName, routeValues, fragment); /// - /// Redirects () to the specified action with - /// set to false and - /// set to true, using the specified , , + /// Redirects () to the specified action with + /// set to false and + /// set to true, using the specified , , /// , and . /// /// The name of the action. /// The name of the controller. /// The route data to use for generating the URL. - /// The fragment to add to the URL. + /// The fragment to add to the URL. /// The created for the response. public virtual RedirectToActionResult RedirectToActionPreserveMethod( string actionName = null, @@ -658,7 +659,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true using the specified . /// /// The name of the action. @@ -669,8 +670,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with - /// set to true using the specified + /// Redirects () to the specified action with + /// set to true using the specified /// and . /// /// The name of the action. @@ -682,8 +683,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with - /// set to true using the specified + /// Redirects () to the specified action with + /// set to true using the specified /// and . /// /// The name of the action. @@ -695,7 +696,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true using the specified , /// , and . /// @@ -712,7 +713,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true using the specified , /// , and . /// @@ -729,7 +730,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true using the specified , /// , , and . /// @@ -753,16 +754,16 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true and - /// set to true, using the specified , , + /// set to true, using the specified , , /// , and . /// /// The name of the action. /// The name of the controller. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToActionResult RedirectToActionPermanentPreserveMethod( string actionName = null, string controllerName = null, @@ -839,14 +840,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified route with + /// Redirects () to the specified route with /// set to false and /// set to true, using the specified , , and . /// /// The name of the route. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToRouteResult RedirectToRoutePreserveMethod( string routeName = null, object routeValues = null, @@ -861,7 +862,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified route with + /// Redirects () to the specified route with /// set to true using the specified . /// /// The name of the route. @@ -872,7 +873,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified route with + /// Redirects () to the specified route with /// set to true using the specified . /// /// The parameters for a route. @@ -896,7 +897,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified route with + /// Redirects () to the specified route with /// set to true using the specified /// and . /// @@ -931,7 +932,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The name of the route. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToRouteResult RedirectToRoutePermanentPreserveMethod( string routeName = null, object routeValues = null, @@ -1074,7 +1075,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => new RedirectToPageResult(pageName, pageHandler, routeValues, permanent: true, fragment: fragment); /// - /// Redirects () to the specified page with + /// Redirects () to the specified page with /// set to false and /// set to true, using the specified , , and . /// @@ -1082,7 +1083,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The page handler to redirect to. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToPageResult RedirectToPagePreserveMethod( string pageName = null, string pageHandler = null, @@ -1107,7 +1108,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The page handler to redirect to. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod( string pageName = null, string pageHandler = null, @@ -1206,12 +1207,17 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The created object for the response. public virtual PartialViewResult Partial(string viewName, object model) { - ViewContext.ViewData.Model = model; + // ViewContext.ViewData is an instance of ViewDataDictionary, but we need an instance + // of ViewDataDictionary. + var viewData = new ViewDataDictionary(MetadataProvider, ViewContext.ViewData.ModelState) + { + Model = model, + }; return new PartialViewResult { ViewName = viewName, - ViewData = ViewContext.ViewData + ViewData = viewData }; } diff --git a/src/Mvc/Mvc.RazorPages/src/PageModel.cs b/src/Mvc/Mvc.RazorPages/src/PageModel.cs index 630084b897..b3dbc5b9da 100644 --- a/src/Mvc/Mvc.RazorPages/src/PageModel.cs +++ b/src/Mvc/Mvc.RazorPages/src/PageModel.cs @@ -139,6 +139,19 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } } + /// + /// Gets or sets the . + /// + public IModelMetadataProvider MetadataProvider + { + get + { + _metadataProvider ??= HttpContext?.RequestServices?.GetRequiredService(); + return _metadataProvider; + } + set => _metadataProvider = value ?? throw new ArgumentNullException(nameof(value)); + } + /// /// Gets the . /// @@ -157,19 +170,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } } - private IModelMetadataProvider MetadataProvider - { - get - { - if (_metadataProvider == null) - { - _metadataProvider = HttpContext?.RequestServices?.GetRequiredService(); - } - - return _metadataProvider; - } - } - private IModelBinderFactory ModelBinderFactory { get @@ -616,7 +616,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => Content(content, (MediaTypeHeaderValue)null); /// - /// Creates a object with by specifying a + /// Creates a object with by specifying a /// string and a content type. /// /// The content to write to the response. @@ -626,7 +626,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => Content(content, MediaTypeHeaderValue.Parse(contentType)); /// - /// Creates a object with by specifying a + /// Creates a object with by specifying a /// string, a , and . /// /// The content to write to the response. @@ -645,7 +645,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Creates a object with by specifying a + /// Creates a object with by specifying a /// string and a . /// /// The content to write to the response. @@ -692,14 +692,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// challenge. /// The created for the response. /// - /// Some authentication schemes, such as cookies, will convert to + /// Some authentication schemes, such as cookies, will convert to /// a redirect to show a login page. /// public virtual ForbidResult Forbid(AuthenticationProperties properties) => new ForbidResult(properties); /// - /// Creates a ( by default) with the + /// Creates a ( by default) with the /// specified authentication schemes and . /// /// used to perform the authentication @@ -780,7 +780,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => new VirtualFileResult(virtualPath, contentType) { FileDownloadName = fileDownloadName }; /// - /// Creates a object that redirects + /// Creates a object that redirects /// () to the specified local . /// /// The local URL to redirect to. @@ -813,7 +813,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Creates a object with set to - /// false and set to true + /// false and set to true /// () using the specified . /// /// The local URL to redirect to. @@ -830,7 +830,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Creates a object with set to - /// true and set to true + /// true and set to true /// () using the specified . /// /// The local URL to redirect to. @@ -924,7 +924,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Creates a object with set to false - /// and set to true () + /// and set to true () /// using the specified . /// /// The URL to redirect to. @@ -941,7 +941,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// Creates a object with set to true - /// and set to true () + /// and set to true () /// using the specified . /// /// The URL to redirect to. @@ -965,7 +965,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToAction(actionName, routeValues: null); /// - /// Redirects () to the specified action using the + /// Redirects () to the specified action using the /// and . /// /// The name of the action. @@ -975,7 +975,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToAction(actionName, controllerName: null, routeValues: routeValues); /// - /// Redirects () to the specified action using the + /// Redirects () to the specified action using the /// and the . /// /// The name of the action. @@ -1034,15 +1034,15 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with - /// set to false and - /// set to true, using the specified , , + /// Redirects () to the specified action with + /// set to false and + /// set to true, using the specified , , /// , and . /// /// The name of the action. /// The name of the pageModel. /// The route data to use for generating the URL. - /// The fragment to add to the URL. + /// The fragment to add to the URL. /// The created for the response. public virtual RedirectToActionResult RedirectToActionPreserveMethod( string actionName = null, @@ -1063,7 +1063,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true using the specified . /// /// The name of the action. @@ -1072,8 +1072,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToActionPermanent(actionName, routeValues: null); /// - /// Redirects () to the specified action with - /// set to true using the specified + /// Redirects () to the specified action with + /// set to true using the specified /// and . /// /// The name of the action. @@ -1083,8 +1083,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToActionPermanent(actionName, controllerName: null, routeValues: routeValues); /// - /// Redirects () to the specified action with - /// set to true using the specified + /// Redirects () to the specified action with + /// set to true using the specified /// and . /// /// The name of the action. @@ -1094,7 +1094,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToActionPermanent(actionName, controllerName, routeValues: null); /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true using the specified , /// , and . /// @@ -1109,7 +1109,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToActionPermanent(actionName, controllerName, routeValues: null, fragment: fragment); /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true using the specified , /// , and . /// @@ -1124,7 +1124,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToActionPermanent(actionName, controllerName, routeValues, fragment: null); /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true using the specified , /// , , and . /// @@ -1151,16 +1151,16 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified action with + /// Redirects () to the specified action with /// set to true and - /// set to true, using the specified , , + /// set to true, using the specified , , /// , and . /// /// The name of the action. /// The name of the pageModel. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToActionResult RedirectToActionPermanentPreserveMethod( string actionName = null, string controllerName = null, @@ -1235,14 +1235,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified route with + /// Redirects () to the specified route with /// set to false and /// set to true, using the specified , , and . /// /// The name of the route. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToRouteResult RedirectToRoutePreserveMethod( string routeName = null, object routeValues = null, @@ -1260,7 +1260,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Redirects () to the specified route with + /// Redirects () to the specified route with /// set to true using the specified . /// /// The name of the route. @@ -1269,7 +1269,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToRoutePermanent(routeName, routeValues: null); /// - /// Redirects () to the specified route with + /// Redirects () to the specified route with /// set to true using the specified . /// /// The parameters for a route. @@ -1289,7 +1289,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => RedirectToRoutePermanent(routeName, routeValues, fragment: null); /// - /// Redirects () to the specified route with + /// Redirects () to the specified route with /// set to true using the specified /// and . /// @@ -1327,7 +1327,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The name of the route. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToRouteResult RedirectToRoutePermanentPreserveMethod( string routeName = null, object routeValues = null, @@ -1494,7 +1494,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages => new RedirectToPageResult(pageName, pageHandler, routeValues, permanent: true, fragment: fragment); /// - /// Redirects () to the specified page with + /// Redirects () to the specified page with /// set to false and /// set to true, using the specified , , and . /// @@ -1502,7 +1502,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The page handler to redirect to. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToPageResult RedirectToPagePreserveMethod( string pageName = null, string pageHandler = null, @@ -1527,7 +1527,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The page handler to redirect to. /// The route data to use for generating the URL. /// The fragment to add to the URL. - /// The created for the response. + /// The created for the response. public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod( string pageName = null, string pageHandler = null, @@ -1631,12 +1631,18 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The created object for the response. public virtual PartialViewResult Partial(string viewName, object model) { - ViewData.Model = model; + // PageModel.ViewData is an instance of ViewDataDictionary, but we need an instance + // of ViewDataDictionary. + + var viewData = new ViewDataDictionary(MetadataProvider, ViewData.ModelState) + { + Model = model, + }; return new PartialViewResult { ViewName = viewName, - ViewData = ViewData + ViewData = viewData }; } diff --git a/src/Mvc/Mvc.RazorPages/test/PageModelTest.cs b/src/Mvc/Mvc.RazorPages/test/PageModelTest.cs index bfb8d6991c..762f22e5d1 100644 --- a/src/Mvc/Mvc.RazorPages/test/PageModelTest.cs +++ b/src/Mvc/Mvc.RazorPages/test/PageModelTest.cs @@ -1898,13 +1898,15 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages public void PartialView_WithName() { // Arrange - var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()); + var modelMetadataProvider = new EmptyModelMetadataProvider(); + var viewData = new ViewDataDictionary(modelMetadataProvider, new ModelStateDictionary()); var pageModel = new TestPageModel { PageContext = new PageContext { ViewData = viewData - } + }, + MetadataProvider = modelMetadataProvider, }; // Act @@ -1913,20 +1915,22 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages // Assert Assert.NotNull(result); Assert.Equal("LoginStatus", result.ViewName); - Assert.Same(viewData, result.ViewData); + Assert.Null(result.Model); } [Fact] public void PartialView_WithNameAndModel() { // Arrange - var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()); + var modelMetadataProvider = new EmptyModelMetadataProvider(); + var viewData = new ViewDataDictionary(modelMetadataProvider, new ModelStateDictionary()); var pageModel = new TestPageModel { PageContext = new PageContext { ViewData = viewData - } + }, + MetadataProvider = modelMetadataProvider, }; var model = new { Username = "Admin" }; @@ -1937,7 +1941,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages Assert.NotNull(result); Assert.Equal("LoginStatus", result.ViewName); Assert.Equal(model, result.Model); - Assert.Same(viewData, result.ViewData); } [Fact] diff --git a/src/Mvc/Mvc.RazorPages/test/PageTest.cs b/src/Mvc/Mvc.RazorPages/test/PageTest.cs index f92db3a934..634986bdff 100644 --- a/src/Mvc/Mvc.RazorPages/test/PageTest.cs +++ b/src/Mvc/Mvc.RazorPages/test/PageTest.cs @@ -1700,14 +1700,17 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages public void PartialView_WithName() { // Arrange - var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()); + var modelMetadataProvider = new EmptyModelMetadataProvider(); + var viewData = new ViewDataDictionary(modelMetadataProvider, new ModelStateDictionary()); var pageModel = new TestPage { ViewContext = new ViewContext { ViewData = viewData - } + }, + MetadataProvider = modelMetadataProvider, }; + viewData.Model = pageModel; // Act var result = pageModel.Partial("LoginStatus"); @@ -1715,21 +1718,24 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages // Assert Assert.NotNull(result); Assert.Equal("LoginStatus", result.ViewName); - Assert.Same(viewData, result.ViewData); + Assert.Null(result.Model); } [Fact] public void PartialView_WithNameAndModel() { // Arrange - var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()); + var modelMetadataProvider = new EmptyModelMetadataProvider(); + var viewData = new ViewDataDictionary(modelMetadataProvider, new ModelStateDictionary()); var pageModel = new TestPage { ViewContext = new ViewContext { ViewData = viewData - } + }, + MetadataProvider = modelMetadataProvider, }; + viewData.Model = pageModel; var model = new { Username = "Admin" }; // Act @@ -1739,7 +1745,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages Assert.NotNull(result); Assert.Equal("LoginStatus", result.ViewName); Assert.Equal(model, result.Model); - Assert.Same(viewData, result.ViewData); } [Fact] diff --git a/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml b/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml index d44cbb6cd2..d4d5241a60 100644 --- a/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml +++ b/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml @@ -1,5 +1,5 @@ @page -@model TestModel +@model PagesHome @{ ViewData["Title"] = "Hello from pages"; diff --git a/src/Mvc/samples/MvcSandbox/Models/TestModel.cs b/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml.cs similarity index 92% rename from src/Mvc/samples/MvcSandbox/Models/TestModel.cs rename to src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml.cs index 29e881e9a4..f33a1370fb 100644 --- a/src/Mvc/samples/MvcSandbox/Models/TestModel.cs +++ b/src/Mvc/samples/MvcSandbox/Pages/PagesHome.cshtml.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages; namespace MvcSandbox { - public class TestModel : PageModel + public class PagesHome : PageModel { public string Name { get; private set; } = "World"; diff --git a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs index 8ecd44c0bd..3fcb25f6fb 100644 --- a/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs +++ b/src/Mvc/test/Mvc.FunctionalTests/RazorPagesTest.cs @@ -144,23 +144,43 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests } [Fact] - public async Task Page_Handler_ReturnPartialWithoutModel() + public async Task PageWithoutModel_ReturnPartial() { // Act - var document = await Client.GetHtmlDocumentAsync("RenderPartialWithoutModel"); + using var document = await Client.GetHtmlDocumentAsync("PageWithoutModelRenderPartial"); var element = document.RequiredQuerySelector("#content"); - Assert.Equal("Welcome, Guest", element.TextContent); + Assert.Equal("Hello from Razor Page", element.TextContent); } [Fact] - public async Task Page_Handler_ReturnPartialWithModel() + public async Task PageWithModel_Works() { // Act - var document = await Client.GetHtmlDocumentAsync("RenderPartialWithModel"); + using var document = await Client.GetHtmlDocumentAsync("RenderPartial"); var element = document.RequiredQuerySelector("#content"); - Assert.Equal("Welcome, Admin", element.TextContent); + Assert.Equal("Hello from RenderPartialModel", element.TextContent); + } + + [Fact] + public async Task PageWithModel_PartialUsingPageModelWorks() + { + // Act + using var document = await Client.GetHtmlDocumentAsync("RenderPartial/UsePageModelAsPartialModel"); + + var element = document.RequiredQuerySelector("#content"); + Assert.Equal("Hello from RenderPartialWithModel", element.TextContent); + } + + [Fact] + public async Task PageWithModel_PartialWithNoModel() + { + // Act + using var document = await Client.GetHtmlDocumentAsync("RenderPartial/NoPartialModel"); + + var element = document.RequiredQuerySelector("#content"); + Assert.Equal("Hello default", element.TextContent); } [Fact] diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/Models/RenderPartialModel.cs b/src/Mvc/test/WebSites/RazorPagesWebSite/Models/RenderPartialModel.cs new file mode 100644 index 0000000000..4d4dd804ee --- /dev/null +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/Models/RenderPartialModel.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace RazorPagesWebSite.Models +{ + public class RenderPartialModel + { + public string Value { get; set; } + } +} diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/PageWithoutModelRenderPartial.cshtml b/src/Mvc/test/WebSites/RazorPagesWebSite/PageWithoutModelRenderPartial.cshtml new file mode 100644 index 0000000000..11f26d2171 --- /dev/null +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/PageWithoutModelRenderPartial.cshtml @@ -0,0 +1,6 @@ +@page +@using RazorPagesWebSite.Models + +@functions { + public IActionResult OnGet() => Partial("_RenderPartial", new RenderPartialModel { Value = "Hello from Razor Page" }); +} diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartial.cshtml b/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartial.cshtml new file mode 100644 index 0000000000..87e98ef7bc --- /dev/null +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartial.cshtml @@ -0,0 +1,7 @@ +@page "{handler?}" +@model RazorPagesWebSite.RenderPartialWithModel + +@{ + throw new Exception("This should not be called"); + +} \ No newline at end of file diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartial.cshtml.cs b/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartial.cshtml.cs new file mode 100644 index 0000000000..03f6a00337 --- /dev/null +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartial.cshtml.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using RazorPagesWebSite.Models; + +namespace RazorPagesWebSite +{ + public class RenderPartialWithModel : PageModel + { + public string Text { get; set; } = $"Hello from {nameof(RenderPartialWithModel)}"; + + public IActionResult OnGet() => Partial("_RenderPartial", new RenderPartialModel { Value = $"Hello from {nameof(RenderPartialModel)}" }); + + public IActionResult OnGetUsePageModelAsPartialModel() => Partial("_RenderPartialPageModel", this); + + public IActionResult OnGetNoPartialModel() => Partial("_RenderPartial"); + } +} diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithModel.cs b/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithModel.cs deleted file mode 100644 index 82711aed2e..0000000000 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace RazorPagesWebSite -{ - public class RenderPartialWithModel : PageModel - { - public IActionResult OnGet() => Partial("_PartialWithModel", this); - - public string Username => "Admin"; - } -} diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithModel.cshtml b/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithModel.cshtml deleted file mode 100644 index 27d507ed75..0000000000 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithModel.cshtml +++ /dev/null @@ -1,4 +0,0 @@ -@page -@model RazorPagesWebSite.RenderPartialWithModel - -

The partial will be loaded here ...

\ No newline at end of file diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithoutModel.cshtml b/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithoutModel.cshtml deleted file mode 100644 index b817a76e67..0000000000 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/RenderPartialWithoutModel.cshtml +++ /dev/null @@ -1,5 +0,0 @@ -@page - -@functions { - public IActionResult OnGet() => Partial("_PartialWithoutModel"); -} diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_PartialWithoutModel.cshtml b/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_PartialWithoutModel.cshtml deleted file mode 100644 index 40b6bbaf56..0000000000 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_PartialWithoutModel.cshtml +++ /dev/null @@ -1 +0,0 @@ -Welcome, Guest \ No newline at end of file diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_RenderPartial.cshtml b/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_RenderPartial.cshtml new file mode 100644 index 0000000000..389bb80c65 --- /dev/null +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_RenderPartial.cshtml @@ -0,0 +1,4 @@ +@using RazorPagesWebSite.Models +@model RenderPartialModel + +@(Model?.Value ?? "Hello default") \ No newline at end of file diff --git a/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_PartialWithModel.cshtml b/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_RenderPartialPageModel.cshtml similarity index 50% rename from src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_PartialWithModel.cshtml rename to src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_RenderPartialPageModel.cshtml index 5c8194f423..46bceaf7ad 100644 --- a/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_PartialWithModel.cshtml +++ b/src/Mvc/test/WebSites/RazorPagesWebSite/Views/Shared/_RenderPartialPageModel.cshtml @@ -1,3 +1,3 @@ @model RazorPagesWebSite.RenderPartialWithModel -Welcome, @Model.Username \ No newline at end of file +@Model.Text \ No newline at end of file