Remove pass-through activator for pages
This change removes a 'pass through' IRazorPageActivator that we were using to avoid the default one initializing the Page twice. The fix is to add an adapter so that the IRazorPage that the RazorView has isn't the *real* page, it's the adapter. The adapter doesn't have anything interesting to activate :).
This commit is contained in:
parent
c3f7613725
commit
b7db6dbc8e
|
|
@ -30,9 +30,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
{
|
{
|
||||||
_metadataProvider = metadataProvider;
|
_metadataProvider = metadataProvider;
|
||||||
|
|
||||||
_viewDataDictionaryType = typeof(ViewDataDictionary<>).MakeGenericType(modelType);
|
|
||||||
_rootFactory = ViewDataDictionaryFactory.CreateFactory(modelType.GetTypeInfo());
|
if (modelType != null)
|
||||||
_nestedFactory = ViewDataDictionaryFactory.CreateNestedFactory(modelType.GetTypeInfo());
|
{
|
||||||
|
_viewDataDictionaryType = typeof(ViewDataDictionary<>).MakeGenericType(modelType);
|
||||||
|
_rootFactory = ViewDataDictionaryFactory.CreateFactory(modelType.GetTypeInfo());
|
||||||
|
_nestedFactory = ViewDataDictionaryFactory.CreateNestedFactory(modelType.GetTypeInfo());
|
||||||
|
}
|
||||||
|
|
||||||
_propertyActivators = PropertyActivator<ViewContext>.GetPropertiesToActivate(
|
_propertyActivators = PropertyActivator<ViewContext>.GetPropertiesToActivate(
|
||||||
pageType,
|
pageType,
|
||||||
|
|
@ -48,7 +52,10 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
throw new ArgumentNullException(nameof(context));
|
throw new ArgumentNullException(nameof(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
context.ViewData = CreateViewDataDictionary(context);
|
if (_viewDataDictionaryType != null)
|
||||||
|
{
|
||||||
|
context.ViewData = CreateViewDataDictionary(context);
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _propertyActivators.Length; i++)
|
for (var i = 0; i < _propertyActivators.Length; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -80,48 +80,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
internal static string FormatLayoutCannotBeRendered(object p0, object p1)
|
internal static string FormatLayoutCannotBeRendered(object p0, object p1)
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("LayoutCannotBeRendered"), p0, p1);
|
=> string.Format(CultureInfo.CurrentCulture, GetString("LayoutCannotBeRendered"), p0, p1);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
|
||||||
/// </summary>
|
|
||||||
internal static string MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword
|
|
||||||
{
|
|
||||||
get => GetString("MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The 'inherits' keyword is not allowed when a '{0}' keyword is used.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatMvcRazorCodeParser_CannotHaveModelAndInheritsKeyword(object p0)
|
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword"), p0);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The '{0}' keyword must be followed by a type name on the same line.
|
|
||||||
/// </summary>
|
|
||||||
internal static string MvcRazorCodeParser_ModelKeywordMustBeFollowedByTypeName
|
|
||||||
{
|
|
||||||
get => GetString("MvcRazorCodeParser_ModelKeywordMustBeFollowedByTypeName");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The '{0}' keyword must be followed by a type name on the same line.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatMvcRazorCodeParser_ModelKeywordMustBeFollowedByTypeName(object p0)
|
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorCodeParser_ModelKeywordMustBeFollowedByTypeName"), p0);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Only one '{0}' statement is allowed in a file.
|
|
||||||
/// </summary>
|
|
||||||
internal static string MvcRazorCodeParser_OnlyOneModelStatementIsAllowed
|
|
||||||
{
|
|
||||||
get => GetString("MvcRazorCodeParser_OnlyOneModelStatementIsAllowed");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Only one '{0}' statement is allowed in a file.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatMvcRazorCodeParser_OnlyOneModelStatementIsAllowed(object p0)
|
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MvcRazorCodeParser_OnlyOneModelStatementIsAllowed"), p0);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// There is no active writing scope to end.
|
/// There is no active writing scope to end.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -234,20 +192,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
internal static string FormatSectionsNotRendered(object p0, object p1, object p2)
|
internal static string FormatSectionsNotRendered(object p0, object p1, object p2)
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("SectionsNotRendered"), p0, p1, p2);
|
=> string.Format(CultureInfo.CurrentCulture, GetString("SectionsNotRendered"), p0, p1, p2);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// View of type '{0}' cannot be activated by '{1}'.
|
|
||||||
/// </summary>
|
|
||||||
internal static string ViewCannotBeActivated
|
|
||||||
{
|
|
||||||
get => GetString("ViewCannotBeActivated");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// View of type '{0}' cannot be activated by '{1}'.
|
|
||||||
/// </summary>
|
|
||||||
internal static string FormatViewCannotBeActivated(object p0, object p1)
|
|
||||||
=> string.Format(CultureInfo.CurrentCulture, GetString("ViewCannotBeActivated"), p0, p1);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// '{0} must be set to access '{1}'.
|
/// '{0} must be set to access '{1}'.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -67,15 +67,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
if (!_activationInfo.TryGetValue(pageType, out propertyActivator))
|
if (!_activationInfo.TryGetValue(pageType, out propertyActivator))
|
||||||
{
|
{
|
||||||
// Look for a property named "Model". If it is non-null, we'll assume this is
|
// Look for a property named "Model". If it is non-null, we'll assume this is
|
||||||
// the equivalent of TModel Model property on RazorPage<TModel>
|
// the equivalent of TModel Model property on RazorPage<TModel>.
|
||||||
var modelProperty = pageType.GetRuntimeProperty(ModelPropertyName);
|
//
|
||||||
if (modelProperty == null)
|
// Otherwise if we don't have a model property the activator will just skip setting
|
||||||
{
|
// the view data.
|
||||||
var message = Resources.FormatViewCannotBeActivated(pageType.FullName, GetType().FullName);
|
var modelType = pageType.GetRuntimeProperty(ModelPropertyName)?.PropertyType;
|
||||||
throw new InvalidOperationException(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
var modelType = modelProperty.PropertyType;
|
|
||||||
propertyActivator = new RazorPagePropertyActivator(
|
propertyActivator = new RazorPagePropertyActivator(
|
||||||
pageType,
|
pageType,
|
||||||
modelType,
|
modelType,
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
/// <remarks>Returns null if <see cref="ViewContext"/> is null.</remarks>
|
/// <remarks>Returns null if <see cref="ViewContext"/> is null.</remarks>
|
||||||
public ITempDataDictionary TempData => ViewContext?.TempData;
|
public ITempDataDictionary TempData => ViewContext?.TempData;
|
||||||
|
|
||||||
protected Stack<TagHelperScopeInfo> TagHelperScopes { get; } = new Stack<TagHelperScopeInfo>();
|
private Stack<TagHelperScopeInfo> TagHelperScopes { get; } = new Stack<TagHelperScopeInfo>();
|
||||||
|
|
||||||
private ITagHelperFactory TagHelperFactory
|
private ITagHelperFactory TagHelperFactory
|
||||||
{
|
{
|
||||||
|
|
@ -755,7 +755,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
public bool Suppressed { get; set; }
|
public bool Suppressed { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected struct TagHelperScopeInfo
|
private struct TagHelperScopeInfo
|
||||||
{
|
{
|
||||||
public TagHelperScopeInfo(ViewBuffer buffer, HtmlEncoder encoder, TextWriter writer)
|
public TagHelperScopeInfo(ViewBuffer buffer, HtmlEncoder encoder, TextWriter writer)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -132,15 +132,6 @@
|
||||||
<data name="LayoutCannotBeRendered" xml:space="preserve">
|
<data name="LayoutCannotBeRendered" xml:space="preserve">
|
||||||
<value>Layout page '{0}' cannot be rendered after '{1}' has been invoked.</value>
|
<value>Layout page '{0}' cannot be rendered after '{1}' has been invoked.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MvcRazorCodeParser_CannotHaveModelAndInheritsKeyword" xml:space="preserve">
|
|
||||||
<value>The 'inherits' keyword is not allowed when a '{0}' keyword is used.</value>
|
|
||||||
</data>
|
|
||||||
<data name="MvcRazorCodeParser_ModelKeywordMustBeFollowedByTypeName" xml:space="preserve">
|
|
||||||
<value>The '{0}' keyword must be followed by a type name on the same line.</value>
|
|
||||||
</data>
|
|
||||||
<data name="MvcRazorCodeParser_OnlyOneModelStatementIsAllowed" xml:space="preserve">
|
|
||||||
<value>Only one '{0}' statement is allowed in a file.</value>
|
|
||||||
</data>
|
|
||||||
<data name="RazorPage_ThereIsNoActiveWritingScopeToEnd" xml:space="preserve">
|
<data name="RazorPage_ThereIsNoActiveWritingScopeToEnd" xml:space="preserve">
|
||||||
<value>There is no active writing scope to end.</value>
|
<value>There is no active writing scope to end.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
@ -165,9 +156,6 @@
|
||||||
<data name="SectionsNotRendered" xml:space="preserve">
|
<data name="SectionsNotRendered" xml:space="preserve">
|
||||||
<value>The following sections have been defined but have not been rendered by the page at '{0}': '{1}'. To ignore an unrendered section call {2}("sectionName").</value>
|
<value>The following sections have been defined but have not been rendered by the page at '{0}': '{1}'. To ignore an unrendered section call {2}("sectionName").</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ViewCannotBeActivated" xml:space="preserve">
|
|
||||||
<value>View of type '{0}' cannot be activated by '{1}'.</value>
|
|
||||||
</data>
|
|
||||||
<data name="ViewContextMustBeSet" xml:space="preserve">
|
<data name="ViewContextMustBeSet" xml:space="preserve">
|
||||||
<value>'{0} must be set to access '{1}'.</value>
|
<value>'{0} must be set to access '{1}'.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
services.TryAddSingleton<IPageModelFactoryProvider, DefaultPageModelFactoryProvider>();
|
services.TryAddSingleton<IPageModelFactoryProvider, DefaultPageModelFactoryProvider>();
|
||||||
|
|
||||||
services.TryAddSingleton<IPageActivatorProvider, DefaultPageActivatorProvider>();
|
services.TryAddSingleton<IPageActivatorProvider, DefaultPageActivatorProvider>();
|
||||||
services.TryAddSingleton<IPageFactoryProvider, DefaultPageFactory>();
|
services.TryAddSingleton<IPageFactoryProvider, DefaultPageFactoryProvider>();
|
||||||
|
|
||||||
services.TryAddSingleton<IPageLoader, DefaultPageLoader>();
|
services.TryAddSingleton<IPageLoader, DefaultPageLoader>();
|
||||||
services.TryAddSingleton<IPageHandlerMethodSelector, DefaultPageHandlerMethodSelector>();
|
services.TryAddSingleton<IPageHandlerMethodSelector, DefaultPageHandlerMethodSelector>();
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@ using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
{
|
{
|
||||||
public class DefaultPageFactory : IPageFactoryProvider
|
public class DefaultPageFactoryProvider : IPageFactoryProvider
|
||||||
{
|
{
|
||||||
private readonly IPageActivatorProvider _pageActivator;
|
private readonly IPageActivatorProvider _pageActivator;
|
||||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||||
private readonly RazorPagePropertyActivator.PropertyValueAccessors _propertyAccessors;
|
private readonly RazorPagePropertyActivator.PropertyValueAccessors _propertyAccessors;
|
||||||
|
|
||||||
public DefaultPageFactory(
|
public DefaultPageFactoryProvider(
|
||||||
IPageActivatorProvider pageActivator,
|
IPageActivatorProvider pageActivator,
|
||||||
IModelMetadataProvider metadataProvider,
|
IModelMetadataProvider metadataProvider,
|
||||||
IUrlHelperFactory urlHelperFactory,
|
IUrlHelperFactory urlHelperFactory,
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
{
|
{
|
||||||
_razorViewEngine = razorViewEngine;
|
_razorViewEngine = razorViewEngine;
|
||||||
_htmlEncoder = htmlEncoder;
|
_htmlEncoder = htmlEncoder;
|
||||||
_razorPageActivator = new PassThruRazorPageActivator(razorPageActivator);
|
_razorPageActivator = razorPageActivator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
_razorViewEngine,
|
_razorViewEngine,
|
||||||
_razorPageActivator,
|
_razorPageActivator,
|
||||||
viewStarts,
|
viewStarts,
|
||||||
result.Page,
|
new RazorPageAdapter(result.Page),
|
||||||
_htmlEncoder);
|
_htmlEncoder);
|
||||||
|
|
||||||
return ExecuteAsync(viewContext, result.ContentType, result.StatusCode);
|
return ExecuteAsync(viewContext, result.ContentType, result.StatusCode);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
// 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 System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Html;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Razor;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
|
{
|
||||||
|
// Implements IRazorPage so that RazorPageBase-derived classes don't get activated twice.
|
||||||
|
//
|
||||||
|
// The page gets activated before handler methods run, but the RazorView will also activate
|
||||||
|
// each page.
|
||||||
|
public class RazorPageAdapter : IRazorPage
|
||||||
|
{
|
||||||
|
private readonly RazorPageBase _page;
|
||||||
|
|
||||||
|
public RazorPageAdapter(RazorPageBase page)
|
||||||
|
{
|
||||||
|
if (page == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(page));
|
||||||
|
}
|
||||||
|
|
||||||
|
_page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewContext ViewContext
|
||||||
|
{
|
||||||
|
get { return _page.ViewContext; }
|
||||||
|
set { _page.ViewContext = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHtmlContent BodyContent
|
||||||
|
{
|
||||||
|
get { return _page.BodyContent; }
|
||||||
|
set { _page.BodyContent = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLayoutBeingRendered
|
||||||
|
{
|
||||||
|
get { return _page.IsLayoutBeingRendered; }
|
||||||
|
set { _page.IsLayoutBeingRendered = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path
|
||||||
|
{
|
||||||
|
get { return _page.Path; }
|
||||||
|
set { _page.Path = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Layout
|
||||||
|
{
|
||||||
|
get { return _page.Layout; }
|
||||||
|
set { _page.Layout = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDictionary<string, RenderAsyncDelegate> PreviousSectionWriters
|
||||||
|
{
|
||||||
|
get { return _page.PreviousSectionWriters; }
|
||||||
|
set { _page.PreviousSectionWriters = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDictionary<string, RenderAsyncDelegate> SectionWriters => _page.SectionWriters;
|
||||||
|
|
||||||
|
public void EnsureRenderedBodyOrSections()
|
||||||
|
{
|
||||||
|
_page.EnsureRenderedBodyOrSections();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
return _page.ExecuteAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,39 +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 System;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Razor;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|
||||||
{
|
|
||||||
public class PassThruRazorPageActivator : IRazorPageActivator
|
|
||||||
{
|
|
||||||
private readonly IRazorPageActivator _pageActivator;
|
|
||||||
|
|
||||||
public PassThruRazorPageActivator(IRazorPageActivator pageActivator)
|
|
||||||
{
|
|
||||||
_pageActivator = pageActivator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Activate(IRazorPage page, ViewContext context)
|
|
||||||
{
|
|
||||||
var razorView = (RazorView)context.View;
|
|
||||||
if (ReferenceEquals(page, razorView.RazorPage))
|
|
||||||
{
|
|
||||||
var actionDescriptor = (CompiledPageActionDescriptor)context.ActionDescriptor;
|
|
||||||
var vddType = typeof(ViewDataDictionary<>);
|
|
||||||
|
|
||||||
var modelTypeInfo = actionDescriptor.ModelTypeInfo ?? actionDescriptor.PageTypeInfo;
|
|
||||||
vddType = vddType.MakeGenericType(modelTypeInfo.AsType());
|
|
||||||
|
|
||||||
context.ViewData = (ViewDataDictionary)Activator.CreateInstance(vddType, context.ViewData);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_pageActivator.Activate(page, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
||||||
/// A base class for a Razor page.
|
/// A base class for a Razor page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PagesBaseClass]
|
[PagesBaseClass]
|
||||||
public abstract class PageBase : RazorPageBase, IRazorPage
|
public abstract class PageBase : RazorPageBase
|
||||||
{
|
{
|
||||||
private IObjectModelValidator _objectValidator;
|
private IObjectModelValidator _objectValidator;
|
||||||
private IModelMetadataProvider _metadataProvider;
|
private IModelMetadataProvider _metadataProvider;
|
||||||
|
|
@ -112,6 +112,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void EnsureRenderedBodyOrSections()
|
public override void EnsureRenderedBodyOrSections()
|
||||||
{
|
{
|
||||||
|
// This will never be called by MVC. MVC only calls this method on layout pages, and a Page can never be a layout page.
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,12 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
|
@ -20,339 +19,185 @@ using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.WebEncoders.Testing;
|
using Microsoft.Extensions.WebEncoders.Testing;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.Razor
|
namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
{
|
{
|
||||||
public class RazorPageActivatorTest
|
public class RazorPageActivatorTest
|
||||||
{
|
{
|
||||||
|
public RazorPageActivatorTest()
|
||||||
|
{
|
||||||
|
DiagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
|
||||||
|
HtmlEncoder = new HtmlTestEncoder();
|
||||||
|
JsonHelper = Mock.Of<IJsonHelper>();
|
||||||
|
MetadataProvider = new EmptyModelMetadataProvider();
|
||||||
|
ModelExpressionProvider = new ModelExpressionProvider(MetadataProvider, new ExpressionTextCache());
|
||||||
|
UrlHelperFactory = new UrlHelperFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DiagnosticSource DiagnosticSource { get; }
|
||||||
|
|
||||||
|
private HtmlEncoder HtmlEncoder { get; }
|
||||||
|
|
||||||
|
private IJsonHelper JsonHelper { get; }
|
||||||
|
|
||||||
|
private IModelMetadataProvider MetadataProvider { get; }
|
||||||
|
|
||||||
|
private IModelExpressionProvider ModelExpressionProvider { get; }
|
||||||
|
|
||||||
|
private IUrlHelperFactory UrlHelperFactory { get; }
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Activate_ActivatesAndContextualizesPropertiesOnViews()
|
public void Activate_ContextualizesServices_AndSetsProperties_OnPage()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
var activator = CreateActivator();
|
||||||
var modelExpressionProvider = new ModelExpressionProvider(modelMetadataProvider, new ExpressionTextCache());
|
|
||||||
var urlHelperFactory = new UrlHelperFactory();
|
|
||||||
var jsonHelper = new JsonHelper(
|
|
||||||
new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared),
|
|
||||||
ArrayPool<char>.Shared);
|
|
||||||
var htmlEncoder = new HtmlTestEncoder();
|
|
||||||
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
|
|
||||||
var activator = new RazorPageActivator(
|
|
||||||
new EmptyModelMetadataProvider(),
|
|
||||||
urlHelperFactory,
|
|
||||||
jsonHelper,
|
|
||||||
diagnosticSource,
|
|
||||||
htmlEncoder,
|
|
||||||
modelExpressionProvider);
|
|
||||||
|
|
||||||
var instance = new TestRazorPage();
|
var instance = new TestRazorPage();
|
||||||
|
var viewData = new ViewDataDictionary<MyModel>(MetadataProvider, new ModelStateDictionary());
|
||||||
|
var viewContext = CreateViewContext();
|
||||||
|
|
||||||
var myService = new MyService();
|
var urlHelper = UrlHelperFactory.GetUrlHelper(viewContext);
|
||||||
var helper = Mock.Of<IHtmlHelper<object>>();
|
|
||||||
|
|
||||||
var serviceProvider = new ServiceCollection()
|
|
||||||
.AddSingleton(myService)
|
|
||||||
.AddSingleton(helper)
|
|
||||||
.AddSingleton(new ExpressionTextCache())
|
|
||||||
.BuildServiceProvider();
|
|
||||||
var httpContext = new DefaultHttpContext
|
|
||||||
{
|
|
||||||
RequestServices = serviceProvider
|
|
||||||
};
|
|
||||||
|
|
||||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
|
||||||
var viewContext = new ViewContext(
|
|
||||||
actionContext,
|
|
||||||
Mock.Of<IView>(),
|
|
||||||
new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()),
|
|
||||||
Mock.Of<ITempDataDictionary>(),
|
|
||||||
TextWriter.Null,
|
|
||||||
new HtmlHelperOptions());
|
|
||||||
|
|
||||||
var urlHelper = urlHelperFactory.GetUrlHelper(viewContext);
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
activator.Activate(instance, viewContext);
|
activator.Activate(instance, viewContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Same(helper, instance.Html);
|
Assert.Same(DiagnosticSource, instance.DiagnosticSource);
|
||||||
Assert.Same(myService, instance.MyService);
|
Assert.Same(HtmlEncoder, instance.HtmlEncoder);
|
||||||
Assert.Same(viewContext, myService.ViewContext);
|
Assert.Same(JsonHelper, instance.Json);
|
||||||
Assert.Same(diagnosticSource, instance.DiagnosticSource);
|
|
||||||
Assert.Same(htmlEncoder, instance.HtmlEncoder);
|
|
||||||
Assert.Same(jsonHelper, instance.Json);
|
|
||||||
Assert.Same(urlHelper, instance.Url);
|
Assert.Same(urlHelper, instance.Url);
|
||||||
|
Assert.Same(viewContext.ViewData, instance.ViewData);
|
||||||
|
|
||||||
|
// Has no [RazorInject] so it shouldn't get injected
|
||||||
Assert.Null(instance.MyService2);
|
Assert.Null(instance.MyService2);
|
||||||
|
|
||||||
|
// We're not testing the IViewContextualizable implementation here because it's a mock.
|
||||||
|
Assert.NotNull(instance.Html);
|
||||||
|
Assert.IsAssignableFrom<IHtmlHelper<object>>(instance.Html);
|
||||||
|
|
||||||
|
var service = instance.MyService;
|
||||||
|
Assert.NotNull(service);
|
||||||
|
Assert.Same(viewContext, service.ViewContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Activate_ThrowsIfTheViewDoesNotDeriveFromRazorViewOfT()
|
public void Activate_ContextualizesServices_AndSetsProperties_OnPageWithoutModel()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
var activator = CreateActivator();
|
||||||
var modelExpressionProvider = new ModelExpressionProvider(modelMetadataProvider, new ExpressionTextCache());
|
|
||||||
var activator = new RazorPageActivator(
|
|
||||||
modelMetadataProvider,
|
|
||||||
new UrlHelperFactory(),
|
|
||||||
new JsonHelper(
|
|
||||||
new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared),
|
|
||||||
ArrayPool<char>.Shared),
|
|
||||||
new DiagnosticListener("Microsoft.AspNetCore"),
|
|
||||||
new HtmlTestEncoder(),
|
|
||||||
modelExpressionProvider);
|
|
||||||
|
|
||||||
var instance = new DoesNotDeriveFromRazorPageOfT();
|
var viewData = new ViewDataDictionary<object>(MetadataProvider, new ModelStateDictionary());
|
||||||
|
var viewContext = CreateViewContext(viewData);
|
||||||
|
|
||||||
var myService = new MyService();
|
var urlHelper = UrlHelperFactory.GetUrlHelper(viewContext);
|
||||||
var helper = Mock.Of<IHtmlHelper<object>>();
|
|
||||||
var serviceProvider = new Mock<IServiceProvider>();
|
|
||||||
var httpContext = new DefaultHttpContext
|
|
||||||
{
|
|
||||||
RequestServices = new ServiceCollection().BuildServiceProvider()
|
|
||||||
};
|
|
||||||
|
|
||||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
var instance = new NoModelPropertyPage();
|
||||||
var viewContext = new ViewContext(
|
|
||||||
actionContext,
|
|
||||||
Mock.Of<IView>(),
|
|
||||||
new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()),
|
|
||||||
Mock.Of<ITempDataDictionary>(),
|
|
||||||
TextWriter.Null,
|
|
||||||
new HtmlHelperOptions());
|
|
||||||
|
|
||||||
// Act and Assert
|
// Act
|
||||||
var ex = Assert.Throws<InvalidOperationException>(() => activator.Activate(instance, viewContext));
|
activator.Activate(instance, viewContext);
|
||||||
var message = $"View of type '{instance.GetType()}' cannot be activated by '{typeof(RazorPageActivator)}'.";
|
|
||||||
Assert.Equal(message, ex.Message);
|
// Assert
|
||||||
|
Assert.Same(DiagnosticSource, instance.DiagnosticSource);
|
||||||
|
Assert.Same(HtmlEncoder, instance.HtmlEncoder);
|
||||||
|
|
||||||
|
// When we don't have a model property, the activator will just leave viewdata alone.
|
||||||
|
Assert.NotNull(viewContext.ViewData);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Activate_InstantiatesNewViewDataDictionaryType_IfTheTypeDoesNotMatch()
|
public void Activate_InstantiatesNewViewDataDictionaryType_IfTheTypeDoesNotMatch()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
var activator = CreateActivator();
|
||||||
var modelExpressionProvider = new ModelExpressionProvider(modelMetadataProvider, new ExpressionTextCache());
|
|
||||||
var activator = new RazorPageActivator(
|
var viewData = new ViewDataDictionary<object>(MetadataProvider, new ModelStateDictionary())
|
||||||
modelMetadataProvider,
|
{
|
||||||
new UrlHelperFactory(),
|
{ "key", "value" },
|
||||||
new JsonHelper(
|
};
|
||||||
new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared),
|
var viewContext = CreateViewContext(viewData);
|
||||||
ArrayPool<char>.Shared),
|
|
||||||
new DiagnosticListener("Microsoft.AspNetCore.Mvc"),
|
var urlHelper = UrlHelperFactory.GetUrlHelper(viewContext);
|
||||||
new HtmlTestEncoder(),
|
|
||||||
modelExpressionProvider);
|
|
||||||
|
|
||||||
var instance = new TestRazorPage();
|
var instance = new TestRazorPage();
|
||||||
|
|
||||||
var myService = new MyService();
|
|
||||||
var helper = Mock.Of<IHtmlHelper<object>>();
|
|
||||||
var serviceProvider = new ServiceCollection()
|
|
||||||
.AddSingleton(myService)
|
|
||||||
.AddSingleton(helper)
|
|
||||||
.AddSingleton(new ExpressionTextCache())
|
|
||||||
.BuildServiceProvider();
|
|
||||||
var httpContext = new DefaultHttpContext
|
|
||||||
{
|
|
||||||
RequestServices = serviceProvider
|
|
||||||
};
|
|
||||||
|
|
||||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
|
||||||
var viewData = new ViewDataDictionary<object>(new EmptyModelMetadataProvider(), new ModelStateDictionary())
|
|
||||||
{
|
|
||||||
Model = new MyModel()
|
|
||||||
};
|
|
||||||
var viewContext = new ViewContext(
|
|
||||||
actionContext,
|
|
||||||
Mock.Of<IView>(),
|
|
||||||
viewData,
|
|
||||||
Mock.Of<ITempDataDictionary>(),
|
|
||||||
TextWriter.Null,
|
|
||||||
new HtmlHelperOptions());
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
activator.Activate(instance, viewContext);
|
activator.Activate(instance, viewContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.IsType<ViewDataDictionary<MyModel>>(viewContext.ViewData);
|
Assert.Same(DiagnosticSource, instance.DiagnosticSource);
|
||||||
}
|
Assert.Same(HtmlEncoder, instance.HtmlEncoder);
|
||||||
|
Assert.Same(JsonHelper, instance.Json);
|
||||||
|
Assert.Same(urlHelper, instance.Url);
|
||||||
|
Assert.Same(viewContext.ViewData, instance.ViewData);
|
||||||
|
|
||||||
[Fact]
|
// The original ViewDataDictionary was replaced.
|
||||||
public void Activate_UsesPassedInViewDataDictionaryInstance_IfPassedInTypeMatches()
|
Assert.NotSame(viewData, viewContext.ViewData);
|
||||||
{
|
Assert.NotSame(viewData, instance.ViewData);
|
||||||
// Arrange
|
|
||||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
|
||||||
var modelExpressionProvider = new ModelExpressionProvider(modelMetadataProvider, new ExpressionTextCache());
|
|
||||||
var activator = new RazorPageActivator(
|
|
||||||
modelMetadataProvider,
|
|
||||||
new UrlHelperFactory(),
|
|
||||||
new JsonHelper(
|
|
||||||
new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared),
|
|
||||||
ArrayPool<char>.Shared),
|
|
||||||
new DiagnosticListener("Microsoft.AspNetCore.Mvc"),
|
|
||||||
new HtmlTestEncoder(),
|
|
||||||
modelExpressionProvider);
|
|
||||||
|
|
||||||
var instance = new TestRazorPage();
|
// But this value is copied
|
||||||
var myService = new MyService();
|
Assert.Equal("value", viewData["key"]);
|
||||||
var helper = Mock.Of<IHtmlHelper<object>>();
|
|
||||||
var serviceProvider = new ServiceCollection()
|
|
||||||
.AddSingleton(myService)
|
|
||||||
.AddSingleton(helper)
|
|
||||||
.AddSingleton(new ExpressionTextCache())
|
|
||||||
.BuildServiceProvider();
|
|
||||||
var httpContext = new DefaultHttpContext
|
|
||||||
{
|
|
||||||
RequestServices = serviceProvider
|
|
||||||
};
|
|
||||||
|
|
||||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
// Has no [RazorInject] so it shouldn't get injected
|
||||||
var viewData = new ViewDataDictionary<MyModel>(new EmptyModelMetadataProvider(), new ModelStateDictionary())
|
Assert.Null(instance.MyService2);
|
||||||
{
|
|
||||||
Model = new MyModel()
|
|
||||||
};
|
|
||||||
var viewContext = new ViewContext(
|
|
||||||
actionContext,
|
|
||||||
Mock.Of<IView>(),
|
|
||||||
viewData,
|
|
||||||
Mock.Of<ITempDataDictionary>(),
|
|
||||||
TextWriter.Null,
|
|
||||||
new HtmlHelperOptions());
|
|
||||||
|
|
||||||
// Act
|
// We're not testing the IViewContextualizable implementation here because it's a mock.
|
||||||
activator.Activate(instance, viewContext);
|
Assert.NotNull(instance.Html);
|
||||||
|
Assert.IsAssignableFrom<IHtmlHelper<object>>(instance.Html);
|
||||||
|
|
||||||
// Assert
|
var service = instance.MyService;
|
||||||
Assert.Same(viewData, viewContext.ViewData);
|
Assert.NotNull(service);
|
||||||
}
|
Assert.Same(viewContext, service.ViewContext);
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Activate_DeterminesModelTypeFromProperty()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
|
||||||
var modelExpressionProvider = new ModelExpressionProvider(modelMetadataProvider, new ExpressionTextCache());
|
|
||||||
var activator = new RazorPageActivator(
|
|
||||||
modelMetadataProvider,
|
|
||||||
new UrlHelperFactory(),
|
|
||||||
new JsonHelper(
|
|
||||||
new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared),
|
|
||||||
ArrayPool<char>.Shared),
|
|
||||||
new DiagnosticListener("Microsoft.AspNetCore.Mvc"),
|
|
||||||
new HtmlTestEncoder(),
|
|
||||||
modelExpressionProvider);
|
|
||||||
|
|
||||||
var instance = new DoesNotDeriveFromRazorPageOfTButHasModelProperty();
|
|
||||||
var myService = new MyService();
|
|
||||||
var helper = Mock.Of<IHtmlHelper<object>>();
|
|
||||||
var serviceProvider = new ServiceCollection()
|
|
||||||
.AddSingleton(myService)
|
|
||||||
.AddSingleton(helper)
|
|
||||||
.AddSingleton(new ExpressionTextCache())
|
|
||||||
.BuildServiceProvider();
|
|
||||||
var httpContext = new DefaultHttpContext
|
|
||||||
{
|
|
||||||
RequestServices = serviceProvider
|
|
||||||
};
|
|
||||||
|
|
||||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
|
||||||
var viewData = new ViewDataDictionary<object>(new EmptyModelMetadataProvider(), new ModelStateDictionary());
|
|
||||||
var viewContext = new ViewContext(
|
|
||||||
actionContext,
|
|
||||||
Mock.Of<IView>(),
|
|
||||||
viewData,
|
|
||||||
Mock.Of<ITempDataDictionary>(),
|
|
||||||
TextWriter.Null,
|
|
||||||
new HtmlHelperOptions());
|
|
||||||
|
|
||||||
// Act
|
|
||||||
activator.Activate(instance, viewContext);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.IsType<ViewDataDictionary<string>>(viewContext.ViewData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Activate_Throws_WhenViewDataPropertyHasIncorrectType()
|
public void Activate_Throws_WhenViewDataPropertyHasIncorrectType()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
var activator = CreateActivator();
|
||||||
var modelExpressionProvider = new ModelExpressionProvider(modelMetadataProvider, new ExpressionTextCache());
|
|
||||||
var activator = new RazorPageActivator(
|
var viewData = new ViewDataDictionary<MyModel>(MetadataProvider, new ModelStateDictionary());
|
||||||
modelMetadataProvider,
|
var viewContext = CreateViewContext(viewData);
|
||||||
new UrlHelperFactory(),
|
|
||||||
new JsonHelper(
|
|
||||||
new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared),
|
|
||||||
ArrayPool<char>.Shared),
|
|
||||||
new DiagnosticListener("Microsoft.AspNetCore.Mvc"),
|
|
||||||
new HtmlTestEncoder(),
|
|
||||||
modelExpressionProvider);
|
|
||||||
|
|
||||||
var instance = new HasIncorrectViewDataPropertyType();
|
var instance = new HasIncorrectViewDataPropertyType();
|
||||||
|
|
||||||
var collection = new ServiceCollection();
|
|
||||||
collection.AddSingleton(new ExpressionTextCache());
|
|
||||||
var httpContext = new DefaultHttpContext
|
|
||||||
{
|
|
||||||
RequestServices = collection.BuildServiceProvider(),
|
|
||||||
};
|
|
||||||
|
|
||||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
|
||||||
var viewContext = new ViewContext(
|
|
||||||
actionContext,
|
|
||||||
Mock.Of<IView>(),
|
|
||||||
new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()),
|
|
||||||
Mock.Of<ITempDataDictionary>(),
|
|
||||||
TextWriter.Null,
|
|
||||||
new HtmlHelperOptions());
|
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
Assert.Throws<InvalidCastException>(() => activator.Activate(instance, viewContext));
|
Assert.Throws<InvalidCastException>(() => activator.Activate(instance, viewContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
private RazorPageActivator CreateActivator()
|
||||||
public void Activate_CanGetUrlHelperFromDependencyInjection()
|
|
||||||
{
|
{
|
||||||
// Arrange
|
return new RazorPageActivator(MetadataProvider, UrlHelperFactory, JsonHelper, DiagnosticSource, HtmlEncoder, ModelExpressionProvider);
|
||||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
}
|
||||||
var modelExpressionProvider = new ModelExpressionProvider(modelMetadataProvider, new ExpressionTextCache());
|
|
||||||
var activator = new RazorPageActivator(
|
|
||||||
modelMetadataProvider,
|
|
||||||
new UrlHelperFactory(),
|
|
||||||
new JsonHelper(
|
|
||||||
new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared),
|
|
||||||
ArrayPool<char>.Shared),
|
|
||||||
new DiagnosticListener("Microsoft.AspNetCore.Mvc"),
|
|
||||||
new HtmlTestEncoder(),
|
|
||||||
modelExpressionProvider);
|
|
||||||
|
|
||||||
var instance = new HasUnusualIUrlHelperProperty();
|
private ViewContext CreateViewContext(ViewDataDictionary viewData = null)
|
||||||
|
{
|
||||||
|
if (viewData == null)
|
||||||
|
{
|
||||||
|
viewData = new ViewDataDictionary(MetadataProvider, new ModelStateDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
// IUrlHelperFactory should not be used. But set it up to match a real configuration.
|
var myService = new MyService();
|
||||||
var collection = new ServiceCollection();
|
var htmlHelper = Mock.Of<IHtmlHelper<object>>();
|
||||||
collection
|
|
||||||
|
var serviceProvider = new ServiceCollection()
|
||||||
|
.AddSingleton(myService)
|
||||||
|
.AddSingleton(htmlHelper)
|
||||||
.AddSingleton(new ExpressionTextCache())
|
.AddSingleton(new ExpressionTextCache())
|
||||||
.AddSingleton<IUrlHelperWrapper, UrlHelperWrapper>();
|
.BuildServiceProvider();
|
||||||
|
|
||||||
var httpContext = new DefaultHttpContext
|
var httpContext = new DefaultHttpContext
|
||||||
{
|
{
|
||||||
RequestServices = collection.BuildServiceProvider(),
|
RequestServices = serviceProvider
|
||||||
};
|
};
|
||||||
|
|
||||||
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
||||||
var viewContext = new ViewContext(
|
return new ViewContext(
|
||||||
actionContext,
|
actionContext,
|
||||||
Mock.Of<IView>(),
|
Mock.Of<IView>(),
|
||||||
new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()),
|
viewData,
|
||||||
Mock.Of<ITempDataDictionary>(),
|
Mock.Of<ITempDataDictionary>(),
|
||||||
TextWriter.Null,
|
TextWriter.Null,
|
||||||
new HtmlHelperOptions());
|
new HtmlHelperOptions());
|
||||||
|
|
||||||
// Act
|
|
||||||
activator.Activate(instance, viewContext);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.NotNull(instance.UrlHelper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class TestPageBase<TModel> : RazorPage<TModel>
|
private abstract class TestPageBase<TModel> : RazorPage<TModel>
|
||||||
|
|
@ -380,11 +225,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class DoesNotDeriveFromRazorPageOfTBase<TModel> : RazorPage
|
private abstract class NoModelPropertyBase<TModel> : RazorPage
|
||||||
{
|
{
|
||||||
|
[RazorInject]
|
||||||
|
public ViewDataDictionary ViewData { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DoesNotDeriveFromRazorPageOfT : DoesNotDeriveFromRazorPageOfTBase<MyModel>
|
private class NoModelPropertyPage : NoModelPropertyBase<MyModel>
|
||||||
{
|
{
|
||||||
public override Task ExecuteAsync()
|
public override Task ExecuteAsync()
|
||||||
{
|
{
|
||||||
|
|
@ -392,16 +239,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DoesNotDeriveFromRazorPageOfTButHasModelProperty : DoesNotDeriveFromRazorPageOfTBase<MyModel>
|
|
||||||
{
|
|
||||||
public string Model { get; set; }
|
|
||||||
|
|
||||||
public override Task ExecuteAsync()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class HasIncorrectViewDataPropertyType : RazorPage<MyModel>
|
private class HasIncorrectViewDataPropertyType : RazorPage<MyModel>
|
||||||
{
|
{
|
||||||
[RazorInject]
|
[RazorInject]
|
||||||
|
|
@ -413,57 +250,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HasUnusualIUrlHelperProperty : RazorPage<MyModel>
|
|
||||||
{
|
|
||||||
[RazorInject]
|
|
||||||
public IUrlHelperWrapper UrlHelper { get; set; }
|
|
||||||
|
|
||||||
public override Task ExecuteAsync()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class UrlHelperWrapper : IUrlHelperWrapper
|
|
||||||
{
|
|
||||||
public ActionContext ActionContext
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Action(UrlActionContext actionContext)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Content(string contentPath)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsLocalUrl(string url)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Link(string routeName, object values)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string RouteUrl(UrlRouteContext routeContext)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface IUrlHelperWrapper : IUrlHelper
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MyService : IViewContextAware
|
private class MyService : IViewContextAware
|
||||||
{
|
{
|
||||||
public ViewContext ViewContext { get; private set; }
|
public ViewContext ViewContext { get; private set; }
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
Assert.NotNull(testPage.ModelExpressionProviderWithInject);
|
Assert.NotNull(testPage.ModelExpressionProviderWithInject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DefaultPageFactory CreatePageFactory(
|
private static DefaultPageFactoryProvider CreatePageFactory(
|
||||||
IPageActivatorProvider pageActivator = null,
|
IPageActivatorProvider pageActivator = null,
|
||||||
IModelMetadataProvider provider = null,
|
IModelMetadataProvider provider = null,
|
||||||
IUrlHelperFactory urlHelperFactory = null,
|
IUrlHelperFactory urlHelperFactory = null,
|
||||||
|
|
@ -269,7 +269,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
HtmlEncoder htmlEncoder = null,
|
HtmlEncoder htmlEncoder = null,
|
||||||
IModelExpressionProvider modelExpressionProvider = null)
|
IModelExpressionProvider modelExpressionProvider = null)
|
||||||
{
|
{
|
||||||
return new DefaultPageFactory(
|
return new DefaultPageFactoryProvider(
|
||||||
pageActivator ?? CreateActivator(),
|
pageActivator ?? CreateActivator(),
|
||||||
provider ?? Mock.Of<IModelMetadataProvider>(),
|
provider ?? Mock.Of<IModelMetadataProvider>(),
|
||||||
urlHelperFactory ?? Mock.Of<IUrlHelperFactory>(),
|
urlHelperFactory ?? Mock.Of<IUrlHelperFactory>(),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue