Пример #1
0
        private void MoveTo(ViewBuffer destination)
        {
            for (var i = 0; i < Pages.Count; i++)
            {
                var page = Pages[i];

                var destinationPage = destination.Pages.Count == 0 ? null : destination.Pages[destination.Pages.Count - 1];

                // If the source page is less or equal to than half full, let's copy it's content to the destination
                // page if possible.
                var isLessThanHalfFull = 2 * page.Count <= page.Capacity;
                if (isLessThanHalfFull &&
                    destinationPage != null &&
                    destinationPage.Capacity - destinationPage.Count >= page.Count)
                {
                    // We have room, let's copy the items.
                    Array.Copy(
                        sourceArray: page.Buffer,
                        sourceIndex: 0,
                        destinationArray: destinationPage.Buffer,
                        destinationIndex: destinationPage.Count,
                        length: page.Count);

                    destinationPage.Count += page.Count;

                    // Now we can return the source page, and it can be reused in the scope of this request.
                    Array.Clear(page.Buffer, 0, page.Count);
                    _bufferScope.ReturnSegment(page.Buffer);
                }
                else
                {
                    // Otherwise, let's just add the source page to the other buffer.
                    destination.Pages.Add(page);
                }
            }

            Pages.Clear();
        }
Пример #2
0
        private async Task <ViewBufferTextWriter> RenderPageAsync(
            TemplatePage page,
            PageContext context,
            bool invokeViewStarts)
        {
            var writer = context.Writer as ViewBufferTextWriter;

            if (writer == null)
            {
                Debug.Assert(_bufferScope != null);

                // If we get here, this is likely the top-level page (not a partial) - this means
                // that context.Writer is wrapping the output stream. We need to buffer, so create a buffered writer.
                ViewBuffer buffer = new ViewBuffer(_bufferScope, page.Path, ViewBuffer.ViewPageSize);
                writer = new ViewBufferTextWriter(buffer, context.Writer.Encoding, _htmlEncoder, context.Writer);
            }
            else
            {
                // This means we're writing something like a partial, where the output needs to be buffered.
                // Create a new buffer, but without the ability to flush.
                ViewBuffer buffer = new ViewBuffer(_bufferScope, page.Path, ViewBuffer.ViewPageSize);
                writer = new ViewBufferTextWriter(buffer, 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;
            var oldFilePath = context.ExecutingFilePath;

            context.Writer            = writer;
            context.ExecutingFilePath = page.Path;

            try
            {
                if (PreRenderCallbacks?.Count > 0)
                {
                    foreach (var callback in PreRenderCallbacks)
                    {
                        try
                        {
                            callback(page);
                        }
                        catch (Exception)
                        {
                            //Ignore
                        }
                    }
                }

                if (invokeViewStarts)
                {
                    // Execute view starts using the same context + writer as the page to render.
                    await RenderViewStartsAsync(context);
                }

                await RenderPageCoreAsync(page, context);

                return(writer);
            }
            finally
            {
                context.Writer            = oldWriter;
                context.ExecutingFilePath = oldFilePath;
            }
        }