Esempio n. 1
0
        private async Task <IHtmlContent> InvokeCoreAsync(
            ViewComponentDescriptor descriptor,
            object arguments)
        {
            var viewBuffer = new ViewBuffer(_viewBufferScope, descriptor.FullName, ViewBuffer.ViewComponentPageSize);

            using (var writer = new ViewBufferTextWriter(viewBuffer, _viewContext.Writer.Encoding))
            {
                var context = new ViewComponentContext(
                    descriptor,
                    PropertyHelper.ObjectToDictionary(arguments),
                    _htmlEncoder,
                    _viewContext,
                    writer);

                var invoker = _invokerFactory.CreateInstance(context);
                if (invoker == null)
                {
                    throw new InvalidOperationException(
                              Resources.FormatViewComponent_IViewComponentFactory_ReturnedNull(descriptor.FullName));
                }

                await invoker.InvokeAsync(context);

                return(viewBuffer);
            }
        }
    public void WriteLine_WritesDataType_AfterFlush()
    {
        // Arrange
        var newLine  = Environment.NewLine;
        var expected = new List <object> {
            "False", newLine, "1.1", newLine, "3", newLine
        };
        var inner  = new Mock <TextWriter>();
        var buffer = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 4);
        var writer = new ViewBufferTextWriter(buffer, Encoding.UTF8, new HtmlTestEncoder(), inner.Object);

        // Act
        writer.Flush();
        writer.WriteLine(false);
        writer.WriteLine(1.1f);
        writer.WriteLine(3L);

        // Assert
        inner.Verify(v => v.Write("False"), Times.Never());
        inner.Verify(v => v.Write("1.1"), Times.Never());
        inner.Verify(v => v.Write("3"), Times.Never());
        inner.Verify(v => v.WriteLine(), Times.Never());

        Assert.Equal(expected, GetValues(buffer));
    }
Esempio n. 3
0
        public async Task <IHtmlContent> InvokeAsync(string viewName, object model, ViewDataDictionary viewData)
        {
            // We always need a view name to invoke
            if (string.IsNullOrEmpty(viewName))
            {
                throw new ArgumentNullException(nameof(viewName));
            }

            var builder = new HtmlContentBuilder();
            var result  = FindView(viewName);

            if (!result.Success)
            {
                throw new Exception($"A view with the name \"{viewName}\" could not be found!");
            }

            var viewBuffer = new ViewBuffer(_viewBufferScope, result.ViewName, ViewBuffer.PartialViewPageSize);

            using (var writer = new ViewBufferTextWriter(viewBuffer, Encoding.UTF8))
            {
                await RenderPartialViewAsync(writer, model, viewData, result.View);
            }

            return(builder.SetHtmlContent(viewBuffer));
        }
Esempio n. 4
0
        private async Task <ViewBufferTextWriter> RenderPageAsync(
            ITemplatePage 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.
                var buffer = new ViewBuffer(_bufferScope, page.Key, 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.
                var buffer = new ViewBuffer(_bufferScope, page.Key, ViewBuffer.ViewPageSize);
                writer = new ViewBufferTextWriter(buffer, context.Writer.Encoding);
            }

            // The writer for the body is passed through the PageContext, allowing things like HtmlHelpers
            // and ViewComponents to reference it.
            var oldWriter   = context.Writer;
            var oldFilePath = context.ExecutingPageKey;

            context.Writer           = writer;
            context.ExecutingPageKey = page.Key;

            try
            {
                //Apply engine-global callbacks
                ExecutePageCallbacks(page, _engine.Options.PreRenderCallbacks.ToList());

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

                await RenderPageCoreAsync(page, context).ConfigureAwait(false);

                return(writer);
            }
            finally
            {
                context.Writer           = oldWriter;
                context.ExecutingPageKey = oldFilePath;
            }
        }
Esempio n. 5
0
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = null;
            ViewEngineResult result = _viewEngine.GetView(string.Empty, $"/{PartialId}", isMainPage: false);
            var viewBuffer          = new ViewBuffer(_viewBufferScope, result.ViewName, ViewBuffer.PartialViewPageSize);

            using (var writer = new ViewBufferTextWriter(viewBuffer, Encoding.UTF8))
            {
                await RenderPartialViewAsync(writer, GetViewModel(), result.View);

                output.Content.SetHtmlContent(viewBuffer);
            }
        }
    public void Write_WritesEmptyCharBuffer()
    {
        // Arrange
        var buffer     = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 4);
        var writer     = new ViewBufferTextWriter(buffer, Encoding.UTF8);
        var charBuffer = new char[0];

        // Act
        writer.Write(charBuffer, 0, 0);

        // Assert
        var actual = GetValues(buffer);

        Assert.Equal <object>(new[] { string.Empty }, actual);
    }
    public async Task WriteLines_WritesCharBuffer()
    {
        // Arrange
        var newLine = Environment.NewLine;
        var buffer  = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 4);
        var writer  = new ViewBufferTextWriter(buffer, Encoding.UTF8);

        // Act
        writer.WriteLine();
        await writer.WriteLineAsync();

        // Assert
        var actual = GetValues(buffer);

        Assert.Equal <object>(new[] { newLine, newLine }, actual);
    }
    public void WriteLine_WritesDataTypes()
    {
        // Arrange
        var newLine  = Environment.NewLine;
        var expected = new List <object> {
            "False", newLine, "1.1", newLine, "3", newLine
        };
        var buffer = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 4);
        var writer = new ViewBufferTextWriter(buffer, Encoding.UTF8);

        // Act
        writer.WriteLine(false);
        writer.WriteLine(1.1f);
        writer.WriteLine(3L);

        // Assert
        Assert.Equal(expected, GetValues(buffer));
    }
Esempio n. 9
0
        /// <summary>
        /// Renders this view for the given <paramref name="viewContext" />
        /// </summary>
        /// <param name="templateService">The template service. This parameter is not used.</param>
        /// <param name="bufferScope">The buffer scope.</param>
        /// <param name="viewContext">The view context.</param>
        public IHtmlContent Render(
            ITemplateService templateService,
            IViewBufferScope bufferScope,
            ViewContext viewContext)
        {
            Guard.NotNull(bufferScope, nameof(bufferScope));
            Guard.NotNull(viewContext, nameof(viewContext));

            var viewBuffer = new ViewBuffer(bufferScope, ViewName, ViewBuffer.PartialViewPageSize);

            using (var writer = new ViewBufferTextWriter(viewBuffer, viewContext.Writer.Encoding))
            {
                var renderContext = new ViewContext(viewContext, View, viewContext.ViewData, writer);
                var renderTask    = View.RenderAsync(renderContext);
                renderTask.GetAwaiter().GetResult();
                return(viewBuffer);
            }
        }
Esempio n. 10
0
        /// <inheritdoc />
        public async Task <IHtmlContent> PartialAsync(
            string partialViewName,
            object model,
            ViewDataDictionary viewData)
        {
            if (partialViewName == null)
            {
                throw new ArgumentNullException(nameof(partialViewName));
            }

            var viewBuffer = new ViewBuffer(_bufferScope, partialViewName, ViewBuffer.PartialViewPageSize);

            using (var writer = new ViewBufferTextWriter(viewBuffer, Encoding.UTF8))
            {
                await RenderPartialCoreAsync(partialViewName, model, viewData, writer);

                return(viewBuffer);
            }
        }
Esempio n. 11
0
    public void Write_WritesDataTypes()
    {
        // Arrange
        var expected = new object[] { "True", "3", "18446744073709551615", "Hello world", "3.14", "2.718", "m" };
        var buffer   = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 4);
        var writer   = new ViewBufferTextWriter(buffer, Encoding.UTF8);

        // Act
        writer.Write(true);
        writer.Write(3);
        writer.Write(ulong.MaxValue);
        writer.Write(new TestClass());
        writer.Write(3.14);
        writer.Write(2.718m);
        writer.Write('m');

        // Assert
        Assert.Equal(expected, GetValues(buffer));
    }
Esempio n. 12
0
        public async Task Write_WithHtmlString_WritesValueWithoutEncoding()
        {
            // Arrange
            var buffer = new ViewBuffer(new TestViewBufferScope(), string.Empty, pageSize: 32);
            var writer = new ViewBufferTextWriter(buffer, Encoding.UTF8);

            var page = CreatePage(p =>
            {
                p.Write(new HtmlString("Hello world"));
            });

            page.PageContext.Writer = writer;

            // Act
            await page.ExecuteAsync();

            // Assert
            Assert.Equal("Hello world", HtmlContentUtilities.HtmlContentToString(buffer));
        }
Esempio n. 13
0
        async Task <ViewBufferTextWriter> RenderPageAsync(IViewBufferScope bufferScope, IRazorPage page, ViewRenderingContext viewRenderingContext)
        {
            var writer = viewRenderingContext.Writer as ViewBufferTextWriter;

            if (writer == 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.
                var buffer = new ViewBuffer(bufferScope, page.GetType().AssemblyQualifiedName, ViewBuffer.ViewPageSize);
                writer = new ViewBufferTextWriter(buffer, viewRenderingContext.Writer.Encoding, this.htmlEncoder, viewRenderingContext.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.
                var buffer = new ViewBuffer(bufferScope, page.GetType().AssemblyQualifiedName, ViewBuffer.ViewPageSize);
                writer = new ViewBufferTextWriter(buffer, viewRenderingContext.Writer.Encoding);
            }

            // The writer for the body is passed through the ViewContext, allowing things like HtmlHelpers
            // and ViewComponents to reference it.
            var oldWriter = viewRenderingContext.Writer;

            //var oldFilePath = context.ExecutingFilePath;

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

            try
            {
                page.RenderingContext = viewRenderingContext;
                await page.ExecuteAsync();

                return(writer);
            }
            finally
            {
                viewRenderingContext.Writer = oldWriter;
                //context.ExecutingFilePath = oldFilePath;
            }
        }
Esempio n. 14
0
        public IHtmlContent Render()
        {
            var defaultActions = GetDefaultActions();
            var modeViewPath   = _readOnly ? DisplayTemplateViewPath : EditorTemplateViewPath;

            foreach (var viewName in GetViewNames())
            {
                var viewEngineResult = _viewEngine.GetView(_viewContext.ExecutingFilePath, viewName, isMainPage: false);
                if (!viewEngineResult.Success)
                {
                    var fullViewName = modeViewPath + "/" + viewName;
                    viewEngineResult = _viewEngine.FindView(_viewContext, fullViewName, isMainPage: false);
                }

                if (viewEngineResult.Success)
                {
                    var viewBuffer = new ViewBuffer(_bufferScope, viewName, ViewBuffer.PartialViewPageSize);
                    using (var writer = new ViewBufferTextWriter(viewBuffer, _viewContext.Writer.Encoding))
                    {
                        // Forcing synchronous behavior so users don't have to await templates.
                        var view = viewEngineResult.View;
                        using (view as IDisposable)
                        {
                            var viewContext = new ViewContext(_viewContext, viewEngineResult.View, _viewData, writer);
                            var renderTask  = viewEngineResult.View.RenderAsync(viewContext);
                            renderTask.GetAwaiter().GetResult();
                            return(viewBuffer);
                        }
                    }
                }

                if (defaultActions.TryGetValue(viewName, out var defaultAction))
                {
                    return(defaultAction(MakeHtmlHelper(_viewContext, _viewData)));
                }
            }

            throw new InvalidOperationException(
                      Resources.FormatTemplateHelpers_NoTemplate(_viewData.ModelExplorer.ModelType.FullName));
        }
Esempio n. 15
0
        private async Task<IHtmlContent> RenderRazorViewAsync(string path, DisplayContext context)
        {
            var viewEngineResult = _viewEngine.Value.ViewEngines.First().FindView(_actionContextAccessor.ActionContext, path, isMainPage: false);
            if (viewEngineResult.Success)
            {
                var bufferScope = context.ViewContext.HttpContext.RequestServices.GetRequiredService<IViewBufferScope>();
                var viewBuffer = new ViewBuffer(bufferScope, viewEngineResult.ViewName, ViewBuffer.PartialViewPageSize);
                using (var writer = new ViewBufferTextWriter(viewBuffer, context.ViewContext.Writer.Encoding))
                {
                    // Forcing synchronous behavior so users don't have to await templates.
                    var view = viewEngineResult.View;
                    using (view as IDisposable)
                    {
                        var viewContext = new ViewContext(context.ViewContext, viewEngineResult.View, context.ViewContext.ViewData, writer);
                        await viewEngineResult.View.RenderAsync(viewContext);
                        return viewBuffer;
                    }
                }
            }

            return null;
        }
Esempio n. 16
0
        /// <inheritdoc />
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (output == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var viewBuffer = new ViewBuffer(_viewBufferScope, Name, ViewBuffer.PartialViewPageSize);

            using (var writer = new ViewBufferTextWriter(viewBuffer, Encoding.UTF8))
            {
                await RenderPartialViewAsync(writer);

                // Reset the TagName. We don't want `partial` to render.
                output.TagName = null;
                output.Content.SetHtmlContent(viewBuffer);
            }
        }
Esempio n. 17
0
    public async Task Write_WritesStringBuffer()
    {
        // Arrange
        var newLine = Environment.NewLine;
        var input1  = "Hello";
        var input2  = "from";
        var input3  = "ASP";
        var input4  = ".Net";
        var buffer  = new ViewBuffer(new TestViewBufferScope(), "some-name", pageSize: 4);
        var writer  = new ViewBufferTextWriter(buffer, Encoding.UTF8);

        // Act
        writer.Write(input1);
        writer.WriteLine(input2);
        await writer.WriteAsync(input3);

        await writer.WriteLineAsync(input4);

        // Assert
        var actual = GetValues(buffer);

        Assert.Equal <object>(new[] { input1, input2, newLine, input3, input4, newLine }, actual);
    }
Esempio n. 18
0
        private async Task <IHtmlContent> RenderRazorViewAsync(string viewName, DisplayContext context)
        {
            var viewEngines = _viewEngine.Value.ViewEngines;

            if (viewEngines.Count == 0)
            {
                throw new InvalidOperationException(string.Format("'{0}.{1}' must not be empty. At least one '{2}' is required to locate a view for rendering.",
                                                                  typeof(MvcViewOptions).FullName,
                                                                  nameof(MvcViewOptions.ViewEngines),
                                                                  typeof(IViewEngine).FullName));
            }

            for (var i = 0; i < viewEngines.Count; i++)
            {
                var viewEngineResult = viewEngines[0].FindView(context.ViewContext, viewName, isMainPage: false);
                if (viewEngineResult.Success)
                {
                    var bufferScope = context.ViewContext.HttpContext.RequestServices.GetRequiredService <IViewBufferScope>();
                    var viewBuffer  = new ViewBuffer(bufferScope, viewEngineResult.ViewName, ViewBuffer.PartialViewPageSize);
                    using (var writer = new ViewBufferTextWriter(viewBuffer, context.ViewContext.Writer.Encoding))
                    {
                        // Forcing synchronous behavior so users don't have to await templates.
                        var view = viewEngineResult.View;
                        using (view as IDisposable)
                        {
                            var viewContext = new ViewContext(context.ViewContext, viewEngineResult.View, context.ViewContext.ViewData, writer);
                            await viewEngineResult.View.RenderAsync(viewContext);

                            return(viewBuffer);
                        }
                    }
                }
            }

            return(null);
        }
Esempio n. 19
0
        private async Task RenderLayoutAsync(
            ViewContext context,
            ViewBufferTextWriter 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>();

            // This loop will execute Layout pages from the inside to the outside. With each
            // iteration, bodyWriter is replaced with the aggregate of all the "body" content
            // (including the layout page we just rendered).
            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;
            }

            // Now we've reached and rendered the outer-most layout page. Nothing left to execute.

            // 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)
            {
                // If IsBuffering - then we've got a bunch of content in the view buffer. How to best deal with it
                // really depends on whether or not we're writing directly to the output or if we're writing to
                // another buffer.
                var viewBufferTextWriter = context.Writer as ViewBufferTextWriter;
                if (viewBufferTextWriter == null || !viewBufferTextWriter.IsBuffering)
                {
                    // This means we're writing to a 'real' writer, probably to the actual output stream.
                    // We're using PagedBufferedTextWriter here to 'smooth' synchronous writes of IHtmlContent values.
                    using (var writer = _bufferScope.CreateWriter(context.Writer))
                    {
                        await bodyWriter.Buffer.WriteToAsync(writer, _htmlEncoder);
                    }
                }
                else
                {
                    // This means we're writing to another buffer. Use MoveTo to combine them.
                    bodyWriter.Buffer.MoveTo(viewBufferTextWriter.Buffer);
                }
            }
        }
Esempio n. 20
0
        public String GenTemplate(string relativePath, IDataTable table, List <IDataTable> tables, ModelConfig cfg)
        {
            //var relativePath = @"/Views/Home/Index1.cshtml";
            if (relativePath == null)
            {
                relativePath = "/Template/实体数据/中文名.cs.cshtml";
            }
            var compiler    = _viewCompilerProvider.GetCompiler();// new Microsoft.AspNetCore.Mvc.Razor.Internal.RazorViewCompiler
            var compileTask = compiler.CompileAsync(relativePath);

            var viewDescriptor = compileTask.GetAwaiter().GetResult();

            var viewType = viewDescriptor.Type;

            var newExpression = Expression.New(viewType);
            var pathProperty  = viewType.GetTypeInfo().GetProperty(nameof(IRazorPage.Path));

            // Generate: page.Path = relativePath;
            // Use the normalized path specified from the result.
            var propertyBindExpression     = Expression.Bind(pathProperty, Expression.Constant(viewDescriptor.RelativePath));
            var objectInitializeExpression = Expression.MemberInit(newExpression, propertyBindExpression);
            var pageFactory = Expression
                              .Lambda <Func <IRazorPage> >(objectInitializeExpression)
                              .Compile();

            var page = pageFactory.Invoke();

            var bufferScope  = HttpContext.RequestServices.GetRequiredService <IViewBufferScope>();
            var buffer       = new ViewBuffer(bufferScope, page.Path, ViewBuffer.ViewPageSize);
            var stringWriter = new StringWriter();
            var writer       = new ViewBufferTextWriter(buffer, Encoding.UTF8, _htmlEncoder, stringWriter);

            page.ViewContext = new ViewContext
            {
                Writer   = writer,
                ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
            };

            if (page is RazorPageBase rPageBase)
            {
                rPageBase.HtmlEncoder    = _htmlEncoder;
                rPageBase.ViewBag.Config = cfg;
                rPageBase.ViewBag.Table  = table;
                rPageBase.ViewBag.Tables = tables;
                //rPageBase.ViewContext.ViewData.Model = 666;
            }

            var task = page.ExecuteAsync();

            //task.Wait();
            if (task.Exception != null)
            {
                XTrace.WriteLine(task.Exception.ToString());
            }

            writer.Flush();

            var res = HttpUtility.HtmlDecode(stringWriter.ToString());

            return(res);
        }