以HtmlStrings形式返回ViewComponent视图,以便在其他ViewComponents中进行操作

时间:2018-07-12 21:20:33

标签: asp.net-mvc razor asp.net-core

我们正在构建一个基于剃须刀的自定义报告引擎,供我们内部使用,到目前为止,一切进展顺利。但是,我们已经开始将初始原型代码分解为ReportViewer视图内部的功能,以使维护变得容易一些,但是我们遇到了一些问题。

原始原型代码(以非常简化的形式)如下所示:

@foreach (var widget in Model.ReportWidgets)
{
    var longSide = Model?.DisplayOptions?.DisplayMedium?.Long ?? 0;
    var units = Model?.DisplayOptions?.DisplayMedium?.Units ?? "px";
    var height = widget.Rows * (longSide / Model.RowsPerPage);
    var width = widget.Columns / Model.Columns * 100;
    <div style="float: left;height: @(height)@(units); width: @(width)%">
        @(await InvokeComponent(widget))
    </div>    
}

我们正在有效地尝试将其分解为看起来更像以下的函数:

public async Task<HtmlString> BuildContainer(IReportWidget widget)
{
    var longSide = Model?.DisplayOptions?.DisplayMedium?.Long ?? 0;
    var units = Model?.DisplayOptions?.DisplayMedium?.Units ?? "px";
    var height = widget.Rows * (longSide / Model.RowsPerPage);
    var width = widget.Columns / Model.Columns * 100;
    var openDeclaration = $"<div style='float:left;height: {height}{units};width: {width}>";
    var component = await InvokeComponent(widget);
    var closeDeclaration = "</div>";

    return new HtmlString(openDeclaration + component + closeDeclaration); 
}

public async Task<IHtmlContent> InvokeComponent(IReportWidget widget)
{
    return await Component.InvokeAsync("AnalyticsWidget", new {widget = widget});
}

但是,由于ViewComponent返回了IViewComponentResult,因此在我们的HtmlString中无法清晰地呈现。相反,它只是吐出Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewBuffer来代替ViewComponent。

我们将如何使它与剃须刀一起使用?

作为参考,我们正在从基于Javascript的客户端版本移植系统。本质上,它们是相同的,但是此版本将在服务器端而不是客户端加载所有组件。

1 个答案:

答案 0 :(得分:1)

在我看来,如果您能够将结果从InvokeComponent转换为String,则应该解决此问题。因此,为什么不尝试从IHtmlContent获取字符串:

System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter writer = new System.IO.StringWriter(sb);
System.Text.Encoding asciiEncoding = System.Text.Encoding.ASCII;
System.Text.Encodings.Web.HtmlEncoder hEncoder= System.Text.Encodings.Web.HtmlEncoder.Default;
component.WriteTo(writer, hEncoder);
String htmlString = writer.toString();