The Silverlight Viewer in the professional edition of ActiveReports 7 provides a very useful tool for viewing reports over the web. The design and creation of a report is not just limited to the viewing experience; the end user should also be able to print the reports efficiently. Though the Silverlight Viewer provides a Print button on the toolbar to handle printing requests, large reports can be a concern to print spoolers. In these cases, the PDF printing option provided by the viewer is a very useful feature to have. ActiveReports supports native Silverlight API printing, but  we can reduce the spooler size from the default Silverlight printing by using PDF Printing.

You can set PDF printing in your Silverlight project to allow printing a document from Silverlight to the PDF format directly. When PDF printing is set up in the Silverlight project, you see a Print dialog appear on clicking the Print button in the SilverlightViewer toolbar as shown below:

SLVPDFPrint

The documentation already explains the PdfPrint functionality here. In this blog, we will cover a common scenario: to load a report into the Silverlight viewer. However, with this approach the PdfPrint functionality does not work. So we will focus on the cause and find a way to work around this issue.

THE PROBLEM:


Typically when loading reports into the Silverlight Viewer we use either the LoadFromService method or the LoadDocument method. The former takes a string value which is the path to the report document. When working with this method the PdfPrint functionality works flawlessly. In this case we are talking about loading an RDF file which is basically a report document containing the report. Here is a nice blog article explaining what an RDF file exactly is.

It is very common for a developer to use a service in his application and send a stream of the report document to the silverlight application. Next the developer will call the LoadDocument method to pass the document stream; however in this case the PdfPrinting will not work.

The reason for this problem is that the pdf which is used for SilverLight viewer printing is exported on the server side. When using the LoadDcoument method, Silverlight viewer doesn't know where is the report on the server side. So the print-used pdf cannot be exported. So what should we do to overcome this issue? Fortunately, there is a workaround available.

THE SOLUTION:


We can follow some additional steps in order to get the PdfPrinting functionality to work which will take care of the limitation which we face. The steps can be summed up as below :

  1. Add a Service to run the report and generate the id.

  2. Add ReportCache class and an IHttpHandler(Report.ashx). They will be used for caching report and getting rdf and print-used pdf. Below is the code used by the handler:
    public class Report : IHttpHandler
    {
    public void ProcessRequest(HttpContext context)
    {
    string id = context.Request.Params["id"];
    if (string.IsNullOrEmpty(id))
    {
    ThrowException(context.Response);
    return;
    }

    SectionDocument sd = ReportCache.GetSectionDocument(id);
    if (sd == null)
    {
    ThrowException(context.Response);
    return;
    }

    string type = context.Request.Params["type"];
    if (string.IsNullOrEmpty(type))
    {
    type = "rdf";
    }

    type = type.ToLower();
    switch (type)
    {
    case "pdf":
    PdfExport pdfExport = new PdfExport();
    string print = context.Request.Params["print"];
    if (print == null)
    {
    print = "false";
    }

    print = print.ToLower();
    if (print != "false")
    {
    pdfExport.Options.OnlyForPrint = true;
    }

    using (var outStream = new MemoryStream())
    {
    // Put output into the stream
    pdfExport.Export(sd, outStream);

    // send the bits
    context.Response.Clear();
    context.Response.ContentType = "application/pdf";
    context.Response.AddHeader("content-disposition", "inline; filename=ActiveReports.PDF");
    context.Response.BinaryWrite(outStream.ToArray());
    }
    break;
    case "rdf":
    default:
    using (MemoryStream outStream = new MemoryStream())
    {
    // Put output into the stream
    sd.Save(outStream);

    // send the bits
    context.Response.Clear();
    context.Response.BinaryWrite(outStream.ToArray());
    }
    break;
    }
    }

    private void ThrowException(HttpResponse response)
    {
    response.ContentType = "text/html";
    response.Write("The specified report was not found on the server");
    response.Flush();
    }

    public bool IsReusable
    {
    get
    {
    return false;
    }
    }
    }

  3. Customize the Silverlight Viewer (refer to this topic from the documentation) :

    • Use DefaultSLViewerTemplates.xaml

    • Customize the print button

    • Bind a command for the print button.




Now we are ready and able to print. For better understanding and a working example, a sample application can be downloaded using the link below:

Download_C#_Sample