ASP.NET MVC: как я могу отобразить элемент управления в поток? - PullRequest
3 голосов
/ 30 августа 2010

Итак, я рендерим частичное представление в памяти, чтобы направить данные 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, или, возможно, я просто что-то напутал.

Если я заменю StreamWriter на StringWriter, он будет работать нормально, но я не могу использовать StringWriter, потому что когда я вызываю .ToString (), я получаю все виды escape-символов, которые портят XSL-FO, и средство визуализации выдает «Illegal».Символы "исключение.

Я справился с этим, создав XmlDocument и загрузив в него строку, но это выглядит как очень окольный способ сделать что-то.Я действительно хотел бы просто захватить выходные данные из HtmlTextWriter и передать их непосредственно в Renderer.Есть ли способ сделать это?

Спасибо!

Ответы [ 2 ]

1 голос
/ 30 августа 2010

Когда вы говорите, что «HtmlTextWriter, похоже, не хочет писать в StreamWriter», означает ли это, что driver.Render не может получить байты из inStream? Я могу придумать две возможности ...

Во-первых, HtmlTextWriter не очищает поток после завершения записи, и в этом случае вам может потребоваться sw.Flush(), прежде чем передать inStream на driver.Render.

Во-вторых, после записи в MemoryStream указатель местоположения будет находиться в конце потока, и любые попытки чтения из него будут давать ноль байтов (поскольку он в конце).

В этом случае установка inStream.Position в 0 или вызов inStream.Seek(0, SeekOrigin.Begin) перед вызовом driver.Render должны исправить это.

Я сталкивался со второй ситуацией несколько раз раньше, так что это мое лучшее предположение.

0 голосов
/ 30 августа 2010

Я не проверял это ВСЕ. .. но это модифицированная версия метода RenderViewToString , который я создал и использовал в других местах:

    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;
    }
...