ASP.NET MVC:如何将控件渲染到流?
-
25-09-2019 - |
题
因此,我在内存中渲染部分视图,以便将视图中的 XSL-FO 数据定向到 PDF 渲染器。
PDF 渲染器可以采用字符串、XmlDocument 或 Stream 作为输入。
这是我想做的:(为了清晰起见进行了编辑)
解决方案取自: http://thriftybliss.spaces.live.com/blog/cns!58DA805F37F31F20!170.entry?wa=wsignin1.0&sa=362921628
var viewPage = new ViewPage();
var viewData = new ViewDataDictionary(model);
viewPage.ViewData = viewData;
var control = viewPage.LoadControl(viewName);
viewPage.Controls.Add(control);
using (var inStream = new MemoryStream())
{
using (var sw = new StreamWriter(inStream))
{
using (var tw = new HtmlTextWriter(sw))
{
viewPage.RenderControl(tw);
}
using (var outStream = new MemoryStream())
{
driver.Render(inStream, outStream);
return outStream.ToArray();
}
}
}
这是可行的,但我不想这样做:
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
}
var xml = new XmlDocument();
xml.LoadXml(sb.ToString());
using (var ms = new MemoryStream())
{
driver.Render(xml, ms);
return ms.ToArray();
}
不幸的是,HtmlTextWriter 似乎不想写入 StreamWriter,或者也许我只是搞砸了其他东西。
如果我用 StringWriter 替换 StreamWriter,它工作正常,但我不能使用 StringWriter,因为当我调用 .ToString() 时,我会得到各种转义字符,这些字符会弄乱 XSL-FO,并且渲染器会抛出“非法字符”异常。
我通过创建一个 XmlDocument 并将字符串加载到其中来解决这个问题,但这似乎是一种非常迂回的做事方式。我真的只想捕获 HtmlTextWriter 的输出并将其直接输入渲染器。有什么办法可以做到这一点吗?
谢谢!
解决方案
当你说“的HtmlTextWriter似乎并不希望写入StreamWriter的”这是否意味着driver.Render
不能得到inStream中的任何字节呢?两种可能性,我能想到...
首先是HtmlTextWriter的不冲水,它的完成写作后的数据流,在这种情况下,你的手进入数据流来sw.Flush()
之前,你可能需要在那里driver.Render
。
二是表示写入的MemoryStream后,位置指针将在流的末尾,任何试图读取从它将产生零个字节(因为它是在端部)。
在这种情况下,设置inStream.Position
为0,或调用inStream.Seek(0, SeekOrigin.Begin)
应该修复它之前调用driver.Render
。
我碰到第二种情况前几次,所以这是我最好的猜测。
其他提示
我根本没有测试过这个。..但它是一个修改版本 渲染视图到字符串方法 我在其他地方制作和使用的:
public static Stream RenderViewToStream<T>(string viewPath, T model, ControllerContext controllerContext)
{
var ms = new MemoryStream();
using (var writer = new StreamWriter(ms))
{
var view = new WebFormView(viewPath);
var vdd = new ViewDataDictionary<T>(model);
var viewCxt = new ViewContext(controllerContext, view, vdd, new TempDataDictionary(), writer);
viewCxt.View.Render(viewCxt, writer);
}
return ms;
}