From 8b03e9ef739b26d1143ceb740d6a8de069d7e42c Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 9 Feb 2017 18:23:01 -0800 Subject: [PATCH] Make PageStart work Move more API to RazorPageBase --- samples/MvcSandbox/Pages/Index.cshtml | 4 + samples/MvcSandbox/Pages/_PageStart.cshtml | 1 + .../RazorPage.cs | 298 +--------------- .../RazorPageBase.cs | 319 ++++++++++++++++-- .../Infrastructure/PageResultExecutor.cs | 2 +- .../Internal/PassThruRazorPageActivator.cs | 14 +- .../Page.cs | 49 +-- 7 files changed, 326 insertions(+), 361 deletions(-) create mode 100644 samples/MvcSandbox/Pages/_PageStart.cshtml diff --git a/samples/MvcSandbox/Pages/Index.cshtml b/samples/MvcSandbox/Pages/Index.cshtml index bde7d9957d..3c565a3b59 100644 --- a/samples/MvcSandbox/Pages/Index.cshtml +++ b/samples/MvcSandbox/Pages/Index.cshtml @@ -1,5 +1,9 @@ @page @model TestModel +@{ + + ViewData["Title"] = "Hello from pages"; +} @functions { diff --git a/samples/MvcSandbox/Pages/_PageStart.cshtml b/samples/MvcSandbox/Pages/_PageStart.cshtml new file mode 100644 index 0000000000..26214bbe6c --- /dev/null +++ b/samples/MvcSandbox/Pages/_PageStart.cshtml @@ -0,0 +1 @@ +@{ Layout = "_Layout";} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorPage.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorPage.cs index 87888c486a..bab23fd534 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorPage.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorPage.cs @@ -4,21 +4,14 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; -using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Html; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Razor.Internal; using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Mvc.ViewFeatures; -using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; -using Microsoft.AspNetCore.Razor.TagHelpers; -using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Mvc.Razor { @@ -28,34 +21,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor public abstract class RazorPage : RazorPageBase, IRazorPage { private readonly HashSet _renderedSections = new HashSet(StringComparer.OrdinalIgnoreCase); - private readonly Stack _tagHelperScopes = new Stack(); - private IUrlHelper _urlHelper; - private ITagHelperFactory _tagHelperFactory; private bool _renderedBody; - private StringWriter _valueBuffer; - private IViewBufferScope _bufferScope; private bool _ignoreBody; private HashSet _ignoredSections; - private TextWriter _pageWriter; - - public RazorPage() - { - SectionWriters = new Dictionary(StringComparer.OrdinalIgnoreCase); - } - - /// - /// An representing the current request execution. - /// - public HttpContext Context => ViewContext?.HttpContext; - - /// - public string Path { get; set; } - - /// - public ViewContext ViewContext { get; set; } - - /// - public string Layout { get; set; } /// /// Gets the to use when this @@ -70,33 +38,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor [RazorInject] public DiagnosticSource DiagnosticSource { get; set; } - /// - /// Gets the that the page is writing output to. - /// - public virtual TextWriter Output - { - get - { - if (ViewContext == null) - { - var message = Resources.FormatViewContextMustBeSet("ViewContext", "Output"); - throw new InvalidOperationException(message); - } - - return ViewContext.Writer; - } - } - /// /// Gets the of the current logged in user. /// public virtual ClaimsPrincipal User => Context?.User; - /// - /// Gets the dynamic view data dictionary. - /// - public dynamic ViewBag => ViewContext?.ViewBag; - /// /// Gets the from the . /// @@ -106,47 +52,11 @@ namespace Microsoft.AspNetCore.Mvc.Razor /// public IHtmlContent BodyContent { get; set; } - /// - public bool IsLayoutBeingRendered { get; set; } - /// public IDictionary PreviousSectionWriters { get; set; } - /// - public IDictionary SectionWriters { get; } - - protected override TextWriter Writer => Output; - protected override HtmlEncoder Encoder => HtmlEncoder; - private ITagHelperFactory TagHelperFactory - { - get - { - if (_tagHelperFactory == null) - { - var services = ViewContext.HttpContext.RequestServices; - _tagHelperFactory = services.GetRequiredService(); - } - - return _tagHelperFactory; - } - } - - private IViewBufferScope BufferScope - { - get - { - if (_bufferScope == null) - { - var services = ViewContext.HttpContext.RequestServices; - _bufferScope = services.GetRequiredService(); - } - - return _bufferScope; - } - } - /// /// Format an error message about using an indexer when the tag helper property is null. /// @@ -165,142 +75,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor propertyName); } - /// - /// Creates and activates a . - /// - /// A type. - /// The activated . - /// - /// must have a parameterless constructor. - /// - public TTagHelper CreateTagHelper() where TTagHelper : ITagHelper - { - return TagHelperFactory.CreateTagHelper(ViewContext); - } - - /// - /// Starts a new writing scope and optionally overrides within that scope. - /// - /// - /// The to use when this handles - /// non- C# expressions. If null, does not change . - /// - /// - /// All writes to the or after calling this method will - /// be buffered until is called. - /// - public void StartTagHelperWritingScope(HtmlEncoder encoder) - { - var buffer = new ViewBuffer(BufferScope, Path, ViewBuffer.TagHelperPageSize); - _tagHelperScopes.Push(new TagHelperScopeInfo(buffer, HtmlEncoder, ViewContext.Writer)); - - // If passed an HtmlEncoder, override the property. - if (encoder != null) - { - HtmlEncoder = encoder; - } - - // We need to replace the ViewContext's Writer to ensure that all content (including content written - // from HTML helpers) is redirected. - ViewContext.Writer = new ViewBufferTextWriter(buffer, ViewContext.Writer.Encoding); - } - - /// - /// Ends the current writing scope that was started by calling . - /// - /// The buffered . - public TagHelperContent EndTagHelperWritingScope() - { - if (_tagHelperScopes.Count == 0) - { - throw new InvalidOperationException(Resources.RazorPage_ThereIsNoActiveWritingScopeToEnd); - } - - var scopeInfo = _tagHelperScopes.Pop(); - - // Get the content written during the current scope. - var tagHelperContent = new DefaultTagHelperContent(); - tagHelperContent.AppendHtml(scopeInfo.Buffer); - - // Restore previous scope. - HtmlEncoder = scopeInfo.Encoder; - ViewContext.Writer = scopeInfo.Writer; - - return tagHelperContent; - } - - /// - /// Starts a new scope for writing attribute values. - /// - /// - /// All writes to the or after calling this method will - /// be buffered until is called. - /// The content will be buffered using a shared within this - /// Nesting of and method calls - /// is not supported. - /// - public void BeginWriteTagHelperAttribute() - { - if (_pageWriter != null) - { - throw new InvalidOperationException(Resources.RazorPage_NestingAttributeWritingScopesNotSupported); - } - - _pageWriter = ViewContext.Writer; - - if (_valueBuffer == null) - { - _valueBuffer = new StringWriter(); - } - - // We need to replace the ViewContext's Writer to ensure that all content (including content written - // from HTML helpers) is redirected. - ViewContext.Writer = _valueBuffer; - - } - - /// - /// Ends the current writing scope that was started by calling . - /// - /// The content buffered by the shared of this . - /// - /// This method assumes that there will be no nesting of - /// and method calls. - /// - public string EndWriteTagHelperAttribute() - { - if (_pageWriter == null) - { - throw new InvalidOperationException(Resources.RazorPage_ThereIsNoActiveWritingScopeToEnd); - } - - var content = _valueBuffer.ToString(); - _valueBuffer.GetStringBuilder().Clear(); - - // Restore previous writer. - ViewContext.Writer = _pageWriter; - _pageWriter = null; - - return content; - } - - public override string Href(string contentPath) - { - if (contentPath == null) - { - throw new ArgumentNullException(nameof(contentPath)); - } - - if (_urlHelper == null) - { - var services = Context.RequestServices; - var factory = services.GetRequiredService(); - _urlHelper = factory.GetUrlHelper(ViewContext); - } - - return _urlHelper.Content(contentPath); - } - /// /// In a Razor layout page, renders the portion of a content page that is not within a named section. /// @@ -371,7 +145,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor /// /// The name of the section to render. /// An empty . - /// The method writes to the and the value returned is a token + /// The method writes to the and the value returned is a token /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the /// value does not represent the rendered content. public HtmlString RenderSection(string name) @@ -390,7 +164,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor /// The section to render. /// Indicates if this section must be rendered. /// An empty . - /// The method writes to the and the value returned is a token + /// The method writes to the and the value returned is a token /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the /// value does not represent the rendered content. public HtmlString RenderSection(string name, bool required) @@ -413,7 +187,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor /// /// A that on completion returns an empty . /// - /// The method writes to the and the value returned is a token + /// The method writes to the and the value returned is a token /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the /// value does not represent the rendered content. public Task RenderSectionAsync(string name) @@ -435,7 +209,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor /// /// A that on completion returns an empty . /// - /// The method writes to the and the value returned is a token + /// The method writes to the and the value returned is a token /// value that allows the Write (produced due to @RenderSection(..)) to succeed. However the /// value does not represent the rendered content. /// if is true and the section @@ -514,40 +288,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor _ignoredSections.Add(sectionName); } - /// - /// Invokes on and - /// on the response stream, writing out any buffered content to the . - /// - /// A that represents the asynchronous flush operation and on - /// completion returns an empty . - /// The value returned is a token value that allows FlushAsync to work directly in an HTML - /// section. However the value does not represent the rendered content. - /// This method also writes out headers, so any modifications to headers must be done before - /// is called. For example, call to send - /// antiforgery cookie token and X-Frame-Options header to client before this method flushes headers out. - /// - public async Task FlushAsync() - { - // If there are active scopes, then we should throw. Cannot flush content that has the potential to change. - if (_tagHelperScopes.Count > 0) - { - throw new InvalidOperationException( - Resources.FormatRazorPage_CannotFlushWhileInAWritingScope(nameof(FlushAsync), Path)); - } - - // Calls to Flush are allowed if the page does not specify a Layout or if it is executing a section in the - // Layout. - if (!IsLayoutBeingRendered && !string.IsNullOrEmpty(Layout)) - { - var message = Resources.FormatLayoutCannotBeRendered(Path, nameof(FlushAsync)); - throw new InvalidOperationException(message); - } - - await Writer.FlushAsync(); - await Context.Response.Body.FlushAsync(); - return HtmlString.Empty; - } - /// public void EnsureRenderedBodyOrSections() { @@ -619,20 +359,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor } } - /// - /// Sets antiforgery cookie and X-Frame-Options header on the response. - /// - /// An empty . - /// Call this method to send antiforgery cookie token and X-Frame-Options header to client - /// before flushes the headers. - public virtual HtmlString SetAntiforgeryCookieAndHeader() - { - var antiforgery = Context.RequestServices.GetRequiredService(); - antiforgery.SetCookieTokenAndHeader(Context); - - return HtmlString.Empty; - } - private void EnsureMethodCanBeInvoked(string methodName) { if (PreviousSectionWriters == null) @@ -640,21 +366,5 @@ namespace Microsoft.AspNetCore.Mvc.Razor throw new InvalidOperationException(Resources.FormatRazorPage_MethodCannotBeCalled(methodName, Path)); } } - - private struct TagHelperScopeInfo - { - public TagHelperScopeInfo(ViewBuffer buffer, HtmlEncoder encoder, TextWriter writer) - { - Buffer = buffer; - Encoder = encoder; - Writer = writer; - } - - public ViewBuffer Buffer { get; } - - public HtmlEncoder Encoder { get; } - - public TextWriter Writer { get; } - } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/RazorPageBase.cs b/src/Microsoft.AspNetCore.Mvc.Razor/RazorPageBase.cs index 05f3e8ca16..9f852567a7 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/RazorPageBase.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/RazorPageBase.cs @@ -2,14 +2,20 @@ // 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.Diagnostics; using System.IO; using System.Text.Encodings.Web; using System.Threading.Tasks; +using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Html; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; using Microsoft.AspNetCore.Razor.Runtime.TagHelpers; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Mvc.Razor { @@ -18,26 +24,245 @@ namespace Microsoft.AspNetCore.Mvc.Razor /// public abstract class RazorPageBase { + private StringWriter _valueBuffer; + private ITagHelperFactory _tagHelperFactory; + private IViewBufferScope _bufferScope; + private TextWriter _pageWriter; private AttributeInfo _attributeInfo; private TagHelperAttributeInfo _tagHelperAttributeInfo; - private StringWriter _valueBuffer; + private IUrlHelper _urlHelper; + + public ViewContext ViewContext { get; set; } + + public string Layout { get; set; } + + /// + /// An representing the current request execution. + /// + public HttpContext Context => ViewContext?.HttpContext; /// /// Gets the that the page is writing output to. /// - protected abstract TextWriter Writer { get; } + /// + /// Gets the that the page is writing output to. + /// + public virtual TextWriter Output + { + get + { + if (ViewContext == null) + { + var message = Resources.FormatViewContextMustBeSet("ViewContext", "Output"); + throw new InvalidOperationException(message); + } - protected abstract HtmlEncoder Encoder { get; } + return ViewContext.Writer; + } + } + + /// + public string Path { get; set; } + + /// + public IDictionary SectionWriters { get; } = + new Dictionary(StringComparer.OrdinalIgnoreCase); + + /// + /// Gets the dynamic view data dictionary. + /// + public dynamic ViewBag => ViewContext?.ViewBag; + + public bool IsLayoutBeingRendered { get; set; } + + protected virtual HtmlEncoder Encoder { get; set; } + + protected Stack TagHelperScopes { get; } = new Stack(); + + private ITagHelperFactory TagHelperFactory + { + get + { + if (_tagHelperFactory == null) + { + var services = ViewContext.HttpContext.RequestServices; + _tagHelperFactory = services.GetRequiredService(); + } + + return _tagHelperFactory; + } + } + + private IViewBufferScope BufferScope + { + get + { + if (_bufferScope == null) + { + var services = ViewContext.HttpContext.RequestServices; + _bufferScope = services.GetRequiredService(); + } + + return _bufferScope; + } + } public abstract Task ExecuteAsync(); /// - /// Writes the specified with HTML encoding to . + /// Creates and activates a . + /// + /// A type. + /// The activated . + /// + /// must have a parameterless constructor. + /// + public TTagHelper CreateTagHelper() where TTagHelper : ITagHelper + { + return TagHelperFactory.CreateTagHelper(ViewContext); + } + + /// + /// Starts a new writing scope and optionally overrides within that scope. + /// + /// + /// The to use when this handles + /// non- C# expressions. If null, does not change . + /// + /// + /// All writes to the or after calling this method will + /// be buffered until is called. + /// + public void StartTagHelperWritingScope(HtmlEncoder encoder) + { + var buffer = new ViewBuffer(BufferScope, Path, ViewBuffer.TagHelperPageSize); + TagHelperScopes.Push(new TagHelperScopeInfo(buffer, Encoder, ViewContext.Writer)); + + // If passed an HtmlEncoder, override the property. + if (encoder != null) + { + Encoder = encoder; + } + + // We need to replace the ViewContext's Writer to ensure that all content (including content written + // from HTML helpers) is redirected. + ViewContext.Writer = new ViewBufferTextWriter(buffer, ViewContext.Writer.Encoding); + } + + /// + /// Ends the current writing scope that was started by calling . + /// + /// The buffered . + public TagHelperContent EndTagHelperWritingScope() + { + var scopeInfo = TagHelperScopes.Pop(); + + // Get the content written during the current scope. + var tagHelperContent = new DefaultTagHelperContent(); + tagHelperContent.AppendHtml(scopeInfo.Buffer); + + // Restore previous scope. + Encoder = scopeInfo.Encoder; + ViewContext.Writer = scopeInfo.Writer; + + return tagHelperContent; + } + + /// + /// Starts a new scope for writing attribute values. + /// + /// + /// All writes to the or after calling this method will + /// be buffered until is called. + /// The content will be buffered using a shared within this + /// Nesting of and method calls + /// is not supported. + /// + public void BeginWriteTagHelperAttribute() + { + _pageWriter = ViewContext.Writer; + + if (_valueBuffer == null) + { + _valueBuffer = new StringWriter(); + } + + // We need to replace the ViewContext's Writer to ensure that all content (including content written + // from HTML helpers) is redirected. + ViewContext.Writer = _valueBuffer; + + } + + /// + /// Ends the current writing scope that was started by calling . + /// + /// The content buffered by the shared of this . + /// + /// This method assumes that there will be no nesting of + /// and method calls. + /// + public string EndWriteTagHelperAttribute() + { + var content = _valueBuffer.ToString(); + _valueBuffer.GetStringBuilder().Clear(); + + // Restore previous writer. + ViewContext.Writer = _pageWriter; + _pageWriter = null; + + return content; + } + + public virtual string Href(string contentPath) + { + if (contentPath == null) + { + throw new ArgumentNullException(nameof(contentPath)); + } + + if (_urlHelper == null) + { + var services = Context.RequestServices; + var factory = services.GetRequiredService(); + _urlHelper = factory.GetUrlHelper(ViewContext); + } + + return _urlHelper.Content(contentPath); + } + + /// + /// Creates a named content section in the page that can be invoked in a Layout page using + /// RenderSection or RenderSectionAsync + /// + /// The name of the section to create. + /// The to execute when rendering the section. + public virtual void DefineSection(string name, RenderAsyncDelegate section) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (section == null) + { + throw new ArgumentNullException(nameof(section)); + } + + if (SectionWriters.ContainsKey(name)) + { + throw new InvalidOperationException(Resources.FormatSectionAlreadyDefined(name)); + } + SectionWriters[name] = section; + } + + + /// + /// Writes the specified with HTML encoding to . /// /// The to write. public virtual void Write(object value) { - WriteTo(Writer, value); + WriteTo(Output, value); } /// @@ -149,12 +374,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor } /// - /// Writes the specified without HTML encoding to . + /// Writes the specified without HTML encoding to . /// /// The to write. public virtual void WriteLiteral(object value) { - WriteLiteralTo(Writer, value); + WriteLiteralTo(Output, value); } /// @@ -176,7 +401,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor } /// - /// Writes the specified without HTML encoding to . + /// Writes the specified without HTML encoding to . /// /// The instance to write to. /// The to write. @@ -201,7 +426,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor int suffixOffset, int attributeValuesCount) { - BeginWriteAttributeTo(Writer, name, prefix, prefixOffset, suffix, suffixOffset, attributeValuesCount); + BeginWriteAttributeTo(Output, name, prefix, prefixOffset, suffix, suffixOffset, attributeValuesCount); } public virtual void BeginWriteAttributeTo( @@ -246,7 +471,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor int valueLength, bool isLiteral) { - WriteAttributeValueTo(Writer, prefix, prefixOffset, value, valueOffset, valueLength, isLiteral); + WriteAttributeValueTo(Output, prefix, prefixOffset, value, valueOffset, valueLength, isLiteral); } public void WriteAttributeValueTo( @@ -297,7 +522,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor public virtual void EndWriteAttribute() { - EndWriteAttributeTo(Writer); + EndWriteAttributeTo(Output); } public virtual void EndWriteAttributeTo(TextWriter writer) @@ -392,7 +617,54 @@ namespace Microsoft.AspNetCore.Mvc.Razor } } - public abstract string Href(string contentPath); + /// + /// Invokes on and + /// on the response stream, writing out any buffered content to the . + /// + /// A that represents the asynchronous flush operation and on + /// completion returns an empty . + /// The value returned is a token value that allows FlushAsync to work directly in an HTML + /// section. However the value does not represent the rendered content. + /// This method also writes out headers, so any modifications to headers must be done before + /// is called. For example, call to send + /// antiforgery cookie token and X-Frame-Options header to client before this method flushes headers out. + /// + + public virtual async Task FlushAsync() + { + // If there are active scopes, then we should throw. Cannot flush content that has the potential to change. + if (TagHelperScopes.Count > 0) + { + throw new InvalidOperationException( + "Resources.FormatRazorPage_CannotFlushWhileInAWritingScope(nameof(FlushAsync), Path))"); + } + + // Calls to Flush are allowed if the page does not specify a Layout or if it is executing a section in the + // Layout. + if (!IsLayoutBeingRendered && !string.IsNullOrEmpty(Layout)) + { + var message = Resources.FormatLayoutCannotBeRendered(Path, nameof(FlushAsync)); + throw new InvalidOperationException(message); + } + + await Output.FlushAsync(); + await Context.Response.Body.FlushAsync(); + return HtmlString.Empty; + } + + /// + /// Sets antiforgery cookie and X-Frame-Options header on the response. + /// + /// An empty . + /// Call this method to send antiforgery cookie token and X-Frame-Options header to client + /// before flushes the headers. + public virtual HtmlString SetAntiforgeryCookieAndHeader() + { + var antiforgery = Context.RequestServices.GetRequiredService(); + antiforgery.SetCookieTokenAndHeader(Context); + + return HtmlString.Empty; + } private void WriteUnprefixedAttributeValueTo(TextWriter writer, object value, bool isLiteral) { @@ -424,13 +696,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor EndContext(); } - /// - /// Creates a named content section in the page. - /// - /// The name of the section to create. - /// The to execute when rendering the section. - public abstract void DefineSection(string name, RenderAsyncDelegate section); - public abstract void BeginContext(int position, int length, bool isLiteral); public abstract void EndContext(); @@ -510,5 +775,21 @@ namespace Microsoft.AspNetCore.Mvc.Razor public bool Suppressed { get; set; } } + + protected struct TagHelperScopeInfo + { + public TagHelperScopeInfo(ViewBuffer buffer, HtmlEncoder encoder, TextWriter writer) + { + Buffer = buffer; + Encoder = encoder; + Writer = writer; + } + + public ViewBuffer Buffer { get; } + + public HtmlEncoder Encoder { get; } + + public TextWriter Writer { get; } + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs index 64d088f2a9..02d07b5410 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs @@ -40,8 +40,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure : base(writerFactory, compositeViewEngine, diagnosticSource) { _razorViewEngine = razorViewEngine; - _razorPageActivator = new PassThruRazorPageActivator(razorPageActivator); _htmlEncoder = htmlEncoder; + _razorPageActivator = new PassThruRazorPageActivator(razorPageActivator); } /// diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PassThruRazorPageActivator.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PassThruRazorPageActivator.cs index 3da7fd9897..3305b07f62 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PassThruRazorPageActivator.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PassThruRazorPageActivator.cs @@ -1,8 +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 System; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal { @@ -20,10 +22,16 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var razorView = (RazorView)context.View; if (ReferenceEquals(page, razorView.RazorPage)) { - return; - } + var pageContext = (PageContext)context; + var vddType = typeof(ViewDataDictionary<>); + vddType = vddType.MakeGenericType(pageContext.ActionDescriptor.ModelTypeInfo.AsType()); - _pageActivator.Activate(page, context); + context.ViewData = (ViewDataDictionary)Activator.CreateInstance(vddType, context.ViewData); + } + else + { + _pageActivator.Activate(page, context); + } } } } diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs index 5514035d79..02d3e43077 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs @@ -4,14 +4,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Razor.Internal; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; -using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Mvc.RazorPages @@ -27,29 +24,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// public IHtmlContent BodyContent { get; set; } - /// - public bool IsLayoutBeingRendered { get; set; } - - /// - public string Layout { get; set; } - - /// - public string Path { get; set; } - /// public IDictionary PreviousSectionWriters { get; set; } - /// - public IDictionary SectionWriters { get; } - /// /// The . /// public PageContext PageContext { get; set; } - /// - public ViewContext ViewContext { get; set; } - /// /// Gets or sets a instance used to instrument the page execution. /// @@ -61,7 +43,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// handles non- C# expressions. /// [RazorInject] - public HtmlEncoder HtmlEncoder { get; set; } + public HtmlEncoder HtmlEncoder + { + get { return Encoder; } + set { Encoder = value; } + } public PageArgumentBinder Binder { @@ -86,10 +72,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } } - protected override HtmlEncoder Encoder => HtmlEncoder; - - protected override TextWriter Writer => ViewContext.Writer; - /// public void EnsureRenderedBodyOrSections() { @@ -131,26 +113,5 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } } - public override string Href(string contentPath) - { - if (contentPath == null) - { - throw new ArgumentNullException(nameof(contentPath)); - } - - if (_urlHelper == null) - { - var services = ViewContext.HttpContext.RequestServices; - var factory = services.GetRequiredService(); - _urlHelper = factory.GetUrlHelper(ViewContext); - } - - return _urlHelper.Content(contentPath); - } - - public override void DefineSection(string name, RenderAsyncDelegate section) - { - - } } }