private async Task RenderLayoutAsync(ViewContext context, RazorTextWriter bodyWriter) { // A layout page can specify another layout page. We'll need to continue // looking for layout pages until they're no longer specified. var previousPage = _page; while (!string.IsNullOrEmpty(previousPage.Layout)) { var layoutPage = _pageFactory.CreateInstance(previousPage.Layout); if (layoutPage == null) { var message = Resources.FormatLayoutCannotBeLocated(previousPage.Layout); throw new InvalidOperationException(message); } layoutPage.PreviousSectionWriters = previousPage.SectionWriters; layoutPage.RenderBodyDelegate = bodyWriter.CopyTo; bodyWriter = await RenderPageAsync(layoutPage, context, executeViewStart : false); // Verify that RenderBody is called, or that RenderSection is called for all sections layoutPage.EnsureBodyAndSectionsWereRendered(); previousPage = layoutPage; } await bodyWriter.CopyToAsync(context.Writer); }
private async Task <RazorTextWriter> RenderPageAsync(IRazorPage page, ViewContext context, bool executeViewStart) { using (var bufferedWriter = new RazorTextWriter(context.Writer.Encoding)) { // The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers // and ViewComponents to reference it. var oldWriter = context.Writer; context.Writer = bufferedWriter; try { if (executeViewStart) { // Execute view starts using the same context + writer as the page to render. await RenderViewStartAsync(context); } await RenderPageCoreAsync(page, context); return(bufferedWriter); } finally { context.Writer = oldWriter; } } }
private async Task<RazorTextWriter> RenderPageAsync(IRazorPage page, ViewContext context, bool executeViewStart) { using (var bufferedWriter = new RazorTextWriter(context.Writer.Encoding)) { // The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers // and ViewComponents to reference it. var oldWriter = context.Writer; context.Writer = bufferedWriter; try { if (executeViewStart) { // Execute view starts using the same context + writer as the page to render. await RenderViewStartAsync(context); } await RenderPageCoreAsync(page, context); return bufferedWriter; } finally { context.Writer = oldWriter; } } }
public async Task Write_WithHtmlString_WritesValueWithoutEncoding() { // Arrange var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var stringCollectionWriter = new StringCollectionTextWriter(Encoding.UTF8); stringCollectionWriter.Write("text1"); stringCollectionWriter.Write("text2"); var page = CreatePage(p => { p.Write(new HtmlString("Hello world")); p.Write(new HtmlString(stringCollectionWriter)); }); page.ViewContext.Writer = writer; // Act await page.ExecuteAsync(); // Assert var buffer = writer.BufferedWriter.Buffer; Assert.Equal(2, buffer.BufferEntries.Count); Assert.Equal("Hello world", buffer.BufferEntries[0]); Assert.Same(stringCollectionWriter.Buffer.BufferEntries, buffer.BufferEntries[1]); }
private async Task RenderLayoutAsync( ViewContext context, RazorTextWriter bodyWriter) { // A layout page can specify another layout page. We'll need to continue // looking for layout pages until they're no longer specified. var previousPage = RazorPage; var renderedLayouts = new List <IRazorPage>(); while (!string.IsNullOrEmpty(previousPage.Layout)) { if (!bodyWriter.IsBuffering) { // Once a call to RazorPage.FlushAsync is made, we can no longer render Layout pages - content has // already been written to the client and the layout content would be appended rather than surround // the body content. Throwing this exception wouldn't return a 500 (since content has already been // written), but a diagnostic component should be able to capture it. var message = Resources.FormatLayoutCannotBeRendered(Path, nameof(Razor.RazorPage.FlushAsync)); throw new InvalidOperationException(message); } var layoutPage = GetLayoutPage(context, previousPage.Path, previousPage.Layout); if (renderedLayouts.Count > 0 && renderedLayouts.Any(l => string.Equals(l.Path, layoutPage.Path, StringComparison.Ordinal))) { // If the layout has been previously rendered as part of this view, we're potentially in a layout // rendering cycle. throw new InvalidOperationException( Resources.FormatLayoutHasCircularReference(previousPage.Path, layoutPage.Path)); } // Notify the previous page that any writes that are performed on it are part of sections being written // in the layout. previousPage.IsLayoutBeingRendered = true; layoutPage.PreviousSectionWriters = previousPage.SectionWriters; layoutPage.BodyContent = bodyWriter.Buffer; bodyWriter = await RenderPageAsync(layoutPage, context, invokeViewStarts : false); renderedLayouts.Add(layoutPage); previousPage = layoutPage; } // Ensure all defined sections were rendered or RenderBody was invoked for page without defined sections. foreach (var layoutPage in renderedLayouts) { layoutPage.EnsureRenderedBodyOrSections(); } if (bodyWriter.IsBuffering) { // Only copy buffered content to the Output if we're currently buffering. await bodyWriter.Buffer.WriteToAsync(context.Writer, _htmlEncoder); } }
private async Task <IBufferedTextWriter> RenderPageAsync( IRazorPage page, ViewContext context, bool executeViewStart) { var razorTextWriter = new RazorTextWriter(context.Writer, context.Writer.Encoding, _htmlEncoder); var writer = (TextWriter)razorTextWriter; var bufferedWriter = (IBufferedTextWriter)razorTextWriter; if (EnableInstrumentation) { writer = _pageExecutionFeature.DecorateWriter(razorTextWriter); bufferedWriter = writer as IBufferedTextWriter; if (bufferedWriter == null) { var message = Resources.FormatInstrumentation_WriterMustBeBufferedTextWriter( nameof(TextWriter), _pageExecutionFeature.GetType().FullName, typeof(IBufferedTextWriter).FullName); throw new InvalidOperationException(message); } } // The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers // and ViewComponents to reference it. var oldWriter = context.Writer; var oldFilePath = context.ExecutingFilePath; context.Writer = writer; context.ExecutingFilePath = page.Path; try { if (executeViewStart) { // Execute view starts using the same context + writer as the page to render. await RenderViewStartAsync(context); } await RenderPageCoreAsync(page, context); return(bufferedWriter); } finally { context.Writer = oldWriter; context.ExecutingFilePath = oldFilePath; writer.Dispose(); } }
private async Task<IBufferedTextWriter> RenderPageAsync(IRazorPage page, ViewContext context, bool executeViewStart) { var razorTextWriter = new RazorTextWriter(context.Writer, context.Writer.Encoding); var writer = (TextWriter)razorTextWriter; var bufferedWriter = (IBufferedTextWriter)razorTextWriter; if (EnableInstrumentation) { writer = _pageExecutionFeature.DecorateWriter(razorTextWriter); bufferedWriter = writer as IBufferedTextWriter; if (bufferedWriter == null) { var message = Resources.FormatInstrumentation_WriterMustBeBufferedTextWriter( nameof(TextWriter), _pageExecutionFeature.GetType().FullName, typeof(IBufferedTextWriter).FullName); throw new InvalidOperationException(message); } } // The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers // and ViewComponents to reference it. var oldWriter = context.Writer; var oldFilePath = context.ExecutingFilePath; context.Writer = writer; context.ExecutingFilePath = page.Path; try { if (executeViewStart) { // Execute view starts using the same context + writer as the page to render. await RenderViewStartAsync(context); } await RenderPageCoreAsync(page, context); return bufferedWriter; } finally { context.Writer = oldWriter; context.ExecutingFilePath = oldFilePath; writer.Dispose(); } }
private async Task RenderLayoutAsync(ViewContext context, RazorTextWriter bodyWriter) { // A layout page can specify another layout page. We'll need to continue // looking for layout pages until they're no longer specified. var previousPage = _razorPage; while (!string.IsNullOrEmpty(previousPage.Layout)) { if (!bodyWriter.IsBuffering) { // Once a call to RazorPage.FlushAsync is made, we can no longer render Layout pages - content has // already been written to the client and the layout content would be appended rather than surround // the body content. Throwing this exception wouldn't return a 500 (since content has already been // written), but a diagnostic component should be able to capture it. var message = Resources.FormatLayoutCannotBeRendered("FlushAsync"); throw new InvalidOperationException(message); } var layoutPage = _pageFactory.CreateInstance(previousPage.Layout); if (layoutPage == null) { var message = Resources.FormatLayoutCannotBeLocated(previousPage.Layout); throw new InvalidOperationException(message); } // Notify the previous page that any writes that are performed on it are part of sections being written // in the layout. previousPage.IsLayoutBeingRendered = true; layoutPage.PreviousSectionWriters = previousPage.SectionWriters; layoutPage.RenderBodyDelegate = bodyWriter.CopyTo; bodyWriter = await RenderPageAsync(layoutPage, context, executeViewStart : false); // Verify that RenderBody is called, or that RenderSection is called for all sections layoutPage.EnsureBodyAndSectionsWereRendered(); previousPage = layoutPage; } if (bodyWriter.IsBuffering) { // Only copy buffered content to the Output if we're currently buffering. await bodyWriter.CopyToAsync(context.Writer); } }
public async Task Write_WithHtmlString_WritesValueWithoutEncoding() { // Arrange var buffer = new ViewBuffer(new TestViewBufferScope(), string.Empty); var writer = new RazorTextWriter(TextWriter.Null, buffer, new HtmlTestEncoder()); var page = CreatePage(p => { p.Write(new HtmlString("Hello world")); }); page.ViewContext.Writer = writer; // Act await page.ExecuteAsync(); // Assert Assert.Equal("Hello world", HtmlContentUtilities.HtmlContentToString(writer.Buffer)); }
private async Task <RazorTextWriter> RenderPageAsync( IRazorPage page, ViewContext context, bool invokeViewStarts) { Debug.Assert(_bufferScope != null); var buffer = new ViewBuffer(_bufferScope, page.Path); var razorTextWriter = new RazorTextWriter(context.Writer, buffer, _htmlEncoder); // The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers // and ViewComponents to reference it. var oldWriter = context.Writer; var oldFilePath = context.ExecutingFilePath; context.Writer = razorTextWriter; context.ExecutingFilePath = page.Path; try { if (invokeViewStarts) { // Execute view starts using the same context + writer as the page to render. await RenderViewStartsAsync(context); } await RenderPageCoreAsync(page, context); return(razorTextWriter); } finally { context.Writer = oldWriter; context.ExecutingFilePath = oldFilePath; razorTextWriter.Dispose(); } }
public async Task Write_WithHtmlString_WritesValueWithoutEncoding() { // Arrange var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8, new CommonTestEncoder()); var page = CreatePage(p => { p.Write(new HtmlString("Hello world")); }); page.ViewContext.Writer = writer; // Act await page.ExecuteAsync(); // Assert var buffer = writer.BufferedWriter.Entries; Assert.Equal(1, buffer.Count); Assert.Equal("Hello world", HtmlContentUtilities.HtmlContentToString(((IHtmlContent)buffer[0]))); }
private async Task RenderLayoutAsync( ViewContext context, RazorTextWriter bodyWriter) { // A layout page can specify another layout page. We'll need to continue // looking for layout pages until they're no longer specified. var previousPage = RazorPage; var renderedLayouts = new List<IRazorPage>(); while (!string.IsNullOrEmpty(previousPage.Layout)) { if (!bodyWriter.IsBuffering) { // Once a call to RazorPage.FlushAsync is made, we can no longer render Layout pages - content has // already been written to the client and the layout content would be appended rather than surround // the body content. Throwing this exception wouldn't return a 500 (since content has already been // written), but a diagnostic component should be able to capture it. var message = Resources.FormatLayoutCannotBeRendered(Path, nameof(Razor.RazorPage.FlushAsync)); throw new InvalidOperationException(message); } var layoutPage = GetLayoutPage(context, previousPage.Path, previousPage.Layout); if (renderedLayouts.Count > 0 && renderedLayouts.Any(l => string.Equals(l.Path, layoutPage.Path, StringComparison.Ordinal))) { // If the layout has been previously rendered as part of this view, we're potentially in a layout // rendering cycle. throw new InvalidOperationException( Resources.FormatLayoutHasCircularReference(previousPage.Path, layoutPage.Path)); } // Notify the previous page that any writes that are performed on it are part of sections being written // in the layout. previousPage.IsLayoutBeingRendered = true; layoutPage.PreviousSectionWriters = previousPage.SectionWriters; layoutPage.BodyContent = bodyWriter.Buffer; bodyWriter = await RenderPageAsync(layoutPage, context, invokeViewStarts: false); renderedLayouts.Add(layoutPage); previousPage = layoutPage; } // Ensure all defined sections were rendered or RenderBody was invoked for page without defined sections. foreach (var layoutPage in renderedLayouts) { layoutPage.EnsureRenderedBodyOrSections(); } if (bodyWriter.IsBuffering) { // Only copy buffered content to the Output if we're currently buffering. await bodyWriter.Buffer.WriteToAsync(context.Writer, _htmlEncoder); } }
private async Task<RazorTextWriter> RenderPageAsync( IRazorPage page, ViewContext context, bool invokeViewStarts) { Debug.Assert(_bufferScope != null); var buffer = new ViewBuffer(_bufferScope, page.Path); var razorTextWriter = new RazorTextWriter(context.Writer, buffer, _htmlEncoder); // The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers // and ViewComponents to reference it. var oldWriter = context.Writer; var oldFilePath = context.ExecutingFilePath; context.Writer = razorTextWriter; context.ExecutingFilePath = page.Path; try { if (invokeViewStarts) { // Execute view starts using the same context + writer as the page to render. await RenderViewStartsAsync(context); } await RenderPageCoreAsync(page, context); return razorTextWriter; } finally { context.Writer = oldWriter; context.ExecutingFilePath = oldFilePath; razorTextWriter.Dispose(); } }
private async Task RenderLayoutAsync(ViewContext context, RazorTextWriter bodyWriter) { // A layout page can specify another layout page. We'll need to continue // looking for layout pages until they're no longer specified. var previousPage = _page; while (!string.IsNullOrEmpty(previousPage.Layout)) { var layoutPage = _pageFactory.CreateInstance(previousPage.Layout); if (layoutPage == null) { var message = Resources.FormatLayoutCannotBeLocated(previousPage.Layout); throw new InvalidOperationException(message); } layoutPage.PreviousSectionWriters = previousPage.SectionWriters; layoutPage.RenderBodyDelegate = bodyWriter.CopyTo; bodyWriter = await RenderPageAsync(layoutPage, context, executeViewStart: false); // Verify that RenderBody is called, or that RenderSection is called for all sections layoutPage.EnsureBodyAndSectionsWereRendered(); previousPage = layoutPage; } await bodyWriter.CopyToAsync(context.Writer); }
public async Task Write_WithHtmlString_WritesValueWithoutEncoding() { // Arrange var writer = new RazorTextWriter(TextWriter.Null, Encoding.UTF8); var stringCollectionWriter = new StringCollectionTextWriter(Encoding.UTF8); stringCollectionWriter.Write("text1"); stringCollectionWriter.Write("text2"); var page = CreatePage(p => { p.Write(new HtmlString("Hello world")); p.Write(new HtmlString(stringCollectionWriter)); }); page.ViewContext.Writer = writer; // Act await page.ExecuteAsync(); // Assert var buffer = writer.BufferedWriter.Buffer; Assert.Equal(3, buffer.BufferEntries.Count); Assert.Equal("Hello world", buffer.BufferEntries[0]); Assert.Equal("text1", buffer.BufferEntries[1]); Assert.Equal("text2", buffer.BufferEntries[2]); }