Пример #1
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 = _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);
        }
Пример #2
0
        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;
                }
            }
        }
Пример #3
0
        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;
                }
            }
        }
Пример #4
0
        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]);
        }
Пример #5
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);
            }
        }
Пример #6
0
        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();
            }
        }
Пример #7
0
        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();
            }
        }
Пример #8
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;

            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);
            }
        }
Пример #9
0
        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));
        }
Пример #10
0
        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();
            }
        }
Пример #11
0
        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])));
        }
Пример #12
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);
            }
        }
Пример #13
0
        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();
            }
        }
Пример #14
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 = _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);
        }
Пример #15
0
        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]);
        }
Пример #16
0
        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));
        }