Archive for December, 2010

Printing a PDF from a web page

The requirement in this case is to print a PDF document, but not allow the user to manipulate the PDF in any other way. The user should see the Print Dialog box and be able to manipulate the settings. This requirement was born out of an auditing policy where the document is audited differently for printing or viewing the PDF.  I found lots of web discussion about printing a pop-up window from the parent window, or trying to print the contents of an IFrame, but none of it worked for me. I was hit with security errors from IE about cross-domain issues, even though my pages were in the same domain, or just got a blank page. So to get a working solution, I had to step out of the web page.

The tool that really allowed me to do this is iTextSharp, a C# implementation of the iText open source java library for manipulating PDF files, and the fact that you can use JavaScript within a PDF file. I used an ASPX page which manipulates and streams the PDF file into a zero-height, zero-width IFrame to keep the user from manipulating the PDF in any way (I realize tech-savvy users could still get the PDF).  I embedded the JavaScript into the PDF, where it runs once the document is loaded and pops up the Print dialog from Adobe Reader (not the browser).

The JavaScript for printing a PDF is not so complex, I embedded it into a function:

protected string GetAutoPrintJs()
{
    var script = new StringBuilder();

    script.Append("var pp = getPrintParams();");
    script.Append("pp.interactive = pp.constants.interactionLevel.full;");
    script.Append("print(pp);");

    return script.ToString();
}

In the code-behind for the ASPX page that will stream the PDF and place the script inside the PDF file, I built this function:

protected void StreamPdf(Stream pdfSource)
{
    var outputStream = new MemoryStream();

    var pdfReader = new PdfReader(pdfSource);

    var pdfStamper = new PdfStamper(pdfReader, outputStream);

    //Add the auto-print javascript
    var writer = pdfStamper.Writer;
    writer.AddJavaScript(GetAutoPrintJs());

    pdfStamper.Close();

    var content = outputStream.ToArray();
    outputStream.Close();
    Response.ContentType = "application/pdf";
    Response.BinaryWrite(content);
    Response.End();
    outputStream.Close();
    outputStream.Dispose();
}

The PDFReader and PDFStamper  classes are members of the iTextSharp library. I used the classes together to get the stream for output and also access to PDFWriter object that allowed me to add the JavaScript.

Configuring CRM 4.0 for SSRS Without the Data Connector

I’m sure the first question someone would ask me is why do this, if installing the  SRS Connector does the job just fine? And I would answer that it does work, and that’s what we did. For the first install. We were creating two instances of CRM, one for a production environment, and one for a test environment. Each instance of the CRM application was on its own virtual web server, and the databases were to be housed in a single physical SQL Server. In this situation, we wanted both the sets of the CRM databases on the same database server. CRM always names the config database MSCRM_Config, so you can’t install a second instance in the same database server because unlike SharePoint, the configuration database name is always the same, and the second install just simply fails. So the initial solution to the problem was to use a second instance of SQL Server on the same physical server. This worked great, until we had to install the SRS Connector on the SQL Server. During the install of the SRS Connector you configure the URL to Reporting Services. The connector only works for one instance of SSRS on the physical box where it is installed. This left us out in the cold for the other instance in terms of the SRS Connector. Since CRM 3.0 didn’t have the SRS Connector, it’s pretty well-known how to configure Kerberos trusts so that SSRS can work from inside CRM without the SRS Connector, so that’s what we needed to do.

There are two ways to accomplish this:

  • Run the CRM site IIS application pool under a domain account
    • Set the SPN for that account
    • Set up trust for delegation to that account
  • Run the CRM site IIS application pool under a local account
    • Set a trust for the machine hosting CRM

Since it seemed to be fewer steps and less to maintain, we went with the second option, setting up an Active Directory trust for the web server hosting CRM.

It was not difficult to set the trust:

  1. On your domain controller (Server 2008 for me), open Active Directory Users and Computers.
  2. Navigate to (or find) the computer hosting CRM
  3. Open the properties of the computer
  4. Choose the Delegation tab
  5. Select Trust this computer for delegation to specified services only
  6. Select Kerberos only
  7. Click the Add button
  8. Click the Users or Computers button
  9. Enter the name of the CRM web server
  10. In the resulting list, choose http in the Service Type Column.
  11. Click a couple of OK buttons
  12. Reset IIS on the CRM server

It should look something like this when you are done:

Any other DC’s may have to sync, but at this point you should be all set.

Posted on:
Posted in CRM, SQL Server, SSRS | Comments Off on Configuring CRM 4.0 for SSRS Without the Data Connector