parent
35601f95b3
commit
037c1ec47d
|
|
@ -30,19 +30,21 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
{
|
||||
_metadataProvider = metadataProvider;
|
||||
|
||||
// In the absence of a model on the current type, we'll attempt to use ViewDataDictionary<object> on the current type.
|
||||
var viewDataDictionaryModelType = modelType ?? typeof(object);
|
||||
|
||||
if (modelType != null)
|
||||
if (viewDataDictionaryModelType != null)
|
||||
{
|
||||
_viewDataDictionaryType = typeof(ViewDataDictionary<>).MakeGenericType(modelType);
|
||||
_rootFactory = ViewDataDictionaryFactory.CreateFactory(modelType.GetTypeInfo());
|
||||
_nestedFactory = ViewDataDictionaryFactory.CreateNestedFactory(modelType.GetTypeInfo());
|
||||
_viewDataDictionaryType = typeof(ViewDataDictionary<>).MakeGenericType(viewDataDictionaryModelType);
|
||||
_rootFactory = ViewDataDictionaryFactory.CreateFactory(viewDataDictionaryModelType.GetTypeInfo());
|
||||
_nestedFactory = ViewDataDictionaryFactory.CreateNestedFactory(viewDataDictionaryModelType.GetTypeInfo());
|
||||
}
|
||||
|
||||
_propertyActivators = PropertyActivator<ViewContext>.GetPropertiesToActivate(
|
||||
pageType,
|
||||
typeof(RazorInjectAttribute),
|
||||
propertyInfo => CreateActivateInfo(propertyInfo, propertyValueAccessors),
|
||||
includeNonPublic: true);
|
||||
pageType,
|
||||
typeof(RazorInjectAttribute),
|
||||
propertyInfo => CreateActivateInfo(propertyInfo, propertyValueAccessors),
|
||||
includeNonPublic: true);
|
||||
}
|
||||
|
||||
public void Activate(object page, ViewContext context)
|
||||
|
|
@ -64,7 +66,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
|||
}
|
||||
}
|
||||
|
||||
private ViewDataDictionary CreateViewDataDictionary(ViewContext context)
|
||||
// Internal for unit testing.
|
||||
internal ViewDataDictionary CreateViewDataDictionary(ViewContext context)
|
||||
{
|
||||
// Create a ViewDataDictionary<TModel> if the ViewContext.ViewData is not set or the type of
|
||||
// ViewContext.ViewData is an incompatible type.
|
||||
|
|
|
|||
|
|
@ -42,11 +42,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
|
||||
public virtual Func<PageContext, ViewContext, object> CreatePageFactory(CompiledPageActionDescriptor actionDescriptor)
|
||||
{
|
||||
if (!typeof(Page).GetTypeInfo().IsAssignableFrom(actionDescriptor.PageTypeInfo))
|
||||
if (!typeof(PageBase).GetTypeInfo().IsAssignableFrom(actionDescriptor.PageTypeInfo))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatActivatedInstance_MustBeAnInstanceOf(
|
||||
_pageActivator.GetType().FullName,
|
||||
typeof(Page).FullName));
|
||||
typeof(PageBase).FullName));
|
||||
}
|
||||
|
||||
var activatorFactory = _pageActivator.CreateActivator(actionDescriptor);
|
||||
|
|
@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
|
||||
return (pageContext, viewContext) =>
|
||||
{
|
||||
var page = (Page)activatorFactory(pageContext, viewContext);
|
||||
var page = (PageBase)activatorFactory(pageContext, viewContext);
|
||||
page.PageContext = pageContext;
|
||||
page.Path = pageContext.ActionDescriptor.RelativePath;
|
||||
page.ViewContext = viewContext;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
|
||||
private Dictionary<string, object> _arguments;
|
||||
private HandlerMethodDescriptor _handler;
|
||||
private Page _page;
|
||||
private PageBase _page;
|
||||
private object _pageModel;
|
||||
private ViewContext _viewContext;
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
_htmlHelperOptions);
|
||||
_viewContext.ExecutingFilePath = _pageContext.ActionDescriptor.RelativePath;
|
||||
|
||||
_page = (Page)CacheEntry.PageFactory(_pageContext, _viewContext);
|
||||
_page = (PageBase)CacheEntry.PageFactory(_pageContext, _viewContext);
|
||||
|
||||
if (_actionDescriptor.ModelTypeInfo == _actionDescriptor.PageTypeInfo)
|
||||
{
|
||||
|
|
@ -271,7 +271,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
|
||||
if (_page == null)
|
||||
{
|
||||
_page = (Page)CacheEntry.PageFactory(_pageContext, _viewContext);
|
||||
_page = (PageBase)CacheEntry.PageFactory(_pageContext, _viewContext);
|
||||
}
|
||||
|
||||
pageResult.Page = _page;
|
||||
|
|
|
|||
|
|
@ -1189,6 +1189,26 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore._InjectedP
|
|||
Assert.StartsWith(expected, responseContent.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public Task InheritsOnViewImportsWorksForPagesWithoutModel()
|
||||
=> InheritsOnViewImportsWorks("Pages/CustomBaseType/Page");
|
||||
|
||||
[Fact]
|
||||
public Task InheritsOnViewImportsWorksForPagesWithModel()
|
||||
=> InheritsOnViewImportsWorks("Pages/CustomBaseType/PageWithModel");
|
||||
|
||||
private async Task InheritsOnViewImportsWorks(string path)
|
||||
{
|
||||
// Arrange
|
||||
var expected = "<custom-base-type-layout>RazorPagesWebSite.CustomPageBase</custom-base-type-layout>";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetStringAsync(path);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, response.Trim());
|
||||
}
|
||||
|
||||
private async Task AddAntiforgeryHeaders(HttpRequestMessage request)
|
||||
{
|
||||
var getResponse = await Client.GetAsync(request.RequestUri);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
// 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.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||
{
|
||||
public class RazorPagePropertyActivatorTest
|
||||
{
|
||||
[Fact]
|
||||
public void CreateViewDataDictionary_MakesNewInstance_WhenValueOnContextIsNull()
|
||||
{
|
||||
// Arrange
|
||||
var activator = new RazorPagePropertyActivator(
|
||||
typeof(TestPage),
|
||||
typeof(TestModel),
|
||||
new TestModelMetadataProvider(),
|
||||
propertyValueAccessors: null);
|
||||
var viewContext = new ViewContext();
|
||||
|
||||
// Act
|
||||
var viewDataDictionary = activator.CreateViewDataDictionary(viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewDataDictionary);
|
||||
Assert.IsType<ViewDataDictionary<TestModel>>(viewDataDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateViewDataDictionary_MakesNewInstanceWithObjectModelType_WhenValueOnContextAndModelTypeAreNull()
|
||||
{
|
||||
// Arrange
|
||||
var activator = new RazorPagePropertyActivator(
|
||||
typeof(TestPage),
|
||||
modelType: null,
|
||||
metadataProvider: new TestModelMetadataProvider(),
|
||||
propertyValueAccessors: null);
|
||||
var viewContext = new ViewContext();
|
||||
|
||||
// Act
|
||||
var viewDataDictionary = activator.CreateViewDataDictionary(viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewDataDictionary);
|
||||
Assert.IsType<ViewDataDictionary<object>>(viewDataDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateViewDataDictionary_CreatesNestedViewDataDictionary_WhenContextInstanceIsNonGeneric()
|
||||
{
|
||||
// Arrange
|
||||
var modelMetadataProvider = new TestModelMetadataProvider();
|
||||
var activator = new RazorPagePropertyActivator(
|
||||
typeof(TestPage),
|
||||
modelType: typeof(TestModel),
|
||||
metadataProvider: modelMetadataProvider,
|
||||
propertyValueAccessors: null);
|
||||
var original = new ViewDataDictionary(modelMetadataProvider, new ModelStateDictionary())
|
||||
{
|
||||
{ "test-key", "test-value" },
|
||||
};
|
||||
var viewContext = new ViewContext
|
||||
{
|
||||
ViewData = original,
|
||||
};
|
||||
|
||||
// Act
|
||||
var viewDataDictionary = activator.CreateViewDataDictionary(viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewDataDictionary);
|
||||
Assert.NotSame(original, viewDataDictionary);
|
||||
Assert.IsType<ViewDataDictionary<TestModel>>(viewDataDictionary);
|
||||
Assert.Equal("test-value", viewDataDictionary["test-key"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateViewDataDictionary_CreatesNestedViewDataDictionary_WhenModelTypeDoesNotMatch()
|
||||
{
|
||||
// Arrange
|
||||
var modelMetadataProvider = new TestModelMetadataProvider();
|
||||
var activator = new RazorPagePropertyActivator(
|
||||
typeof(TestPage),
|
||||
modelType: typeof(TestModel),
|
||||
metadataProvider: modelMetadataProvider,
|
||||
propertyValueAccessors: null);
|
||||
var original = new ViewDataDictionary<object>(modelMetadataProvider, new ModelStateDictionary())
|
||||
{
|
||||
{ "test-key", "test-value" },
|
||||
};
|
||||
var viewContext = new ViewContext
|
||||
{
|
||||
ViewData = original,
|
||||
};
|
||||
|
||||
// Act
|
||||
var viewDataDictionary = activator.CreateViewDataDictionary(viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewDataDictionary);
|
||||
Assert.NotSame(original, viewDataDictionary);
|
||||
Assert.IsType<ViewDataDictionary<TestModel>>(viewDataDictionary);
|
||||
Assert.Equal("test-value", viewDataDictionary["test-key"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateViewDataDictionary_CreatesNestedViewDataDictionary_WhenNullModelTypeDoesNotMatch()
|
||||
{
|
||||
// Arrange
|
||||
var modelMetadataProvider = new TestModelMetadataProvider();
|
||||
var activator = new RazorPagePropertyActivator(
|
||||
typeof(TestPage),
|
||||
modelType: null,
|
||||
metadataProvider: modelMetadataProvider,
|
||||
propertyValueAccessors: null);
|
||||
var original = new ViewDataDictionary<TestModel>(modelMetadataProvider, new ModelStateDictionary())
|
||||
{
|
||||
{ "test-key", "test-value" },
|
||||
};
|
||||
var viewContext = new ViewContext
|
||||
{
|
||||
ViewData = original,
|
||||
};
|
||||
|
||||
// Act
|
||||
var viewDataDictionary = activator.CreateViewDataDictionary(viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewDataDictionary);
|
||||
Assert.NotSame(original, viewDataDictionary);
|
||||
Assert.IsType<ViewDataDictionary<object>>(viewDataDictionary);
|
||||
Assert.Equal("test-value", viewDataDictionary["test-key"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateViewDataDictionary_ReturnsInstanceOnContext_IfModelTypeMatches()
|
||||
{
|
||||
// Arrange
|
||||
var modelMetadataProvider = new TestModelMetadataProvider();
|
||||
var activator = new RazorPagePropertyActivator(
|
||||
typeof(TestPage),
|
||||
modelType: typeof(TestModel),
|
||||
metadataProvider: modelMetadataProvider,
|
||||
propertyValueAccessors: null);
|
||||
var original = new ViewDataDictionary<TestModel>(modelMetadataProvider, new ModelStateDictionary())
|
||||
{
|
||||
{ "test-key", "test-value" },
|
||||
};
|
||||
var viewContext = new ViewContext
|
||||
{
|
||||
ViewData = original,
|
||||
};
|
||||
|
||||
// Act
|
||||
var viewDataDictionary = activator.CreateViewDataDictionary(viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewDataDictionary);
|
||||
Assert.Same(original, viewDataDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateViewDataDictionary_ReturnsInstanceOnContext_WithNullModelType()
|
||||
{
|
||||
// Arrange
|
||||
var modelMetadataProvider = new TestModelMetadataProvider();
|
||||
var activator = new RazorPagePropertyActivator(
|
||||
typeof(TestPage),
|
||||
modelType: null,
|
||||
metadataProvider: modelMetadataProvider,
|
||||
propertyValueAccessors: null);
|
||||
var original = new ViewDataDictionary<object>(modelMetadataProvider, new ModelStateDictionary());
|
||||
var viewContext = new ViewContext
|
||||
{
|
||||
ViewData = original,
|
||||
};
|
||||
|
||||
// Act
|
||||
var viewDataDictionary = activator.CreateViewDataDictionary(viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewDataDictionary);
|
||||
Assert.Same(original, viewDataDictionary);
|
||||
}
|
||||
|
||||
private class TestPage
|
||||
{
|
||||
}
|
||||
|
||||
private class TestModel
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => factoryProvider.CreatePageFactory(descriptor));
|
||||
Assert.Equal(
|
||||
$"Page created by '{pageActivator.GetType()}' must be an instance of '{typeof(Page)}'.",
|
||||
$"Page created by '{pageActivator.GetType()}' must be an instance of '{typeof(PageBase)}'.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace RazorPagesWebSite
|
||||
{
|
||||
public abstract class CustomPageBase : PageBase
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@page
|
||||
@GetType().BaseType.FullName
|
||||
|
|
@ -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.
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace RazorPagesWebSite
|
||||
{
|
||||
public class PageWithModel : PageModel
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@page
|
||||
@model PageWithModel
|
||||
@GetType().BaseType.FullName
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@using RazorPagesWebSite
|
||||
@inherits CustomPageBase
|
||||
|
|
@ -0,0 +1 @@
|
|||
@{ Layout = "../Shared/_CustomBaseTypeLayout"; }
|
||||
|
|
@ -0,0 +1 @@
|
|||
<custom-base-type-layout>@RenderBody()</custom-base-type-layout>
|
||||
Loading…
Reference in New Issue