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)); }
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)); }
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; } }
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)); }
/// <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); } }
/// <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); } }
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)); }
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)); }
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; } }
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)); }
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; }
/// <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); } }
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); }
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); }
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); } } }
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); }