Pergunta

Portanto, estou fazendo uma visão parcial na memória para direcionar os dados XSL-FO na visualização para um renderizador de PDF.

O renderizador do PDF pode pegar uma string, xmldocument ou fluxo como entrada.

Aqui está o que eu gostaria de fazer: (Editado para clareza)

Solução tirada de: 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();
        }
    }
}

Aqui está o que funciona, mas o que eu preferiria não fazer:

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

Infelizmente, o htmltextwriter não parece querer escrever para o streamwriter, ou talvez eu apenas estrague outra coisa.

Se eu substituir o StreamWriter pelo StringWriter, ele funcionar bem, mas não posso usar o StringWriter porque, quando chamo de .toString (), recebo todos os tipos de caracteres de fuga que atrapalham o XSL-Fo e o renderizador lança uma exceção "caracteres ilegais".

Eu adquiri isso criando um XMLDocument e carregando a string nisso, mas parece uma maneira muito indireta de fazer as coisas. Eu realmente gostaria de apenas capturar a saída do htmltextwriter e alimentá -lo diretamente no renderizador. Há alguma maneira de fazer isso?

Obrigado!

Foi útil?

Solução

Quando você diz "htmltextwriter não parece querer escrever para o streamwriter" isso significa que isso significa que driver.Render Não consegue tirar bytes do encontro? Duas possibilidades que eu consigo pensar ...

Primeiro é que o htmltextwriter não está descarregando o fluxo depois que terminar de escrever, nesse caso, você pode precisar de um sw.Flush() lá antes de entregar o encontro a driver.Render.

O segundo é que, depois de escrever para o MemoryStream, o ponteiro de localização estará no final do fluxo, e qualquer tentativa de ler dele produzirá zero bytes (pois está no final).

Nesse caso, configuração inStream.Position para 0, ou chamando inStream.Seek(0, SeekOrigin.Begin) antes de ligar driver.Render deve consertar isso.

Eu já encontrei a segunda situação algumas vezes antes, então esse é o meu melhor palpite.

Outras dicas

Eu não testei nada disso... mas é uma versão modificada de um Método RenderViewToString que eu fiz e uso em outro lugar:

    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;
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top