Monday, May 12, 2014

Displaying HTML Tags in SSRS

SSRS doesn't have full support of html. Currently SSRS reports is supporting following basic HTML tags:
1) Hyperlinks: <A HREF>
2) Fonts: <FONT>
3) Header, style and block elements: <H {n}>, <DIV>, <SPAN>, <P>, <DIV>, <LI>, <HN>
4) Text format: <B>, <I>, <U>, <S>
5) List handling: <OL>, <UL>, <LI>
If you have above mentioned tags in your fields and variables then by following steps you can render them:
     1)  After dragging the column in SSRS Design Repot Page you can Right Click inside the column > Select Create Placeholder in Place holder Properties tab, select “HTML-Interpret HTML tags as styles” Radio Button.
 

If you need more tags - then it's not possible right now by this approach but in one of our client’s report we got to display HTML table tag. In this blog I'm trying to explain actual challenge faced with help of dummy projects. Hope this will help someone someday :)

We had followed different approach for this; we have converted whatever HTML data we were getting into filed into Image and then displayed that image into SSRS report. For HTML text to Image conversion we have used “HtmlRenderer.DLL” that can be found at following location http://htmlrenderer.codeplex.com/releases/view/100328. It’s Lightweight single dll and is 100% managed C# code without any external dependencies.  You may download the Demo application to explore HTML Renderer capabilities. I’ll be focusing only on Image displaying options with SSRS.

This can be achieved by following three approaches:

  • Saving Image into Database
  • Using Web Service
  • Using Custom Code in SSRS itself
I’ll discuss more about all approaches and provide sample test code herewith.
Saving Image into Database
For this approach While saving Data in DB for getting display into  report  we can convert associated HTML data as image and save as byte array into DB . Then SSRS report will Bind that binary data into image control.
For sample I’m assuming I have a table named “Testing_SSRSImages”, and it had a column named “Picture” which holds generated image as byte array. Now to render this image we can follow following steps:

  1.  We can query this in SSRS data set and get into one of the field.
  2.   Drag Image control into cell and configure Image Properties
a.       Select Image source as Database
b.      Select filed and MIME Type
  

For next two approaches too we’ll use same HtmlRenderer.DLL to convert HTML input to image. But by them we don’t need to store binary data into Database. If you don’t prefer to store images into DB then these two approaches can be proved helpful.
Using Web Service:
Let’s assume we have a WCF service which returns binary data with following contract

  [ServiceContract(Namespace = "http://localhost:56040/Service1")]
    public interface IService1
    {
        [OperationContract]
        byte[] GernrateImagefromHtml(string textToHTML);
    }


SSRS doesn’t have very good support for web services too. We have to use basic Http binding, with security mode none. Binding configuration will be as follows
<system.serviceModel>
              <behaviors>
                     <serviceBehaviors>
                           <behavior name="WcfService1.Service1Behavior">
                                  <serviceMetadata httpGetEnabled="true" />
                                  <serviceDebug includeExceptionDetailInFaults="true" />
                           </behavior>
                     </serviceBehaviors>
              </behaviors>
              <services>
                     <service behaviorConfiguration="WcfService1.Service1Behavior"
                      name="WcfService1.Service1">
                           <endpoint address=""
                           binding="basicHttpBinding"  bindingConfiguration="userHttps" contract="WcfService1.IService1">
                                  <identity>
                                         <dns value="localhost" />
                                  </identity>
                           </endpoint>
                           <endpoint address="mex"
                           binding="mexHttpBinding"
                           contract="IMetadataExchange" />
                     </service>
              </services>
              <bindings>
                     <basicHttpBinding>
                           <binding name="userHttps">
                                  <security mode="None" />
                           </binding>
                     </basicHttpBinding>
              </bindings>
              <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
       </system.serviceModel>




Then we have to follow following steps at SSRS level: 
  •   Configure data source type XML and Connection string will be service URL
  • Create Data set with above created data source. Now create text query to have SOAP request to service as follows
<Query>
<Method Name="GernrateImagefromHtml" Namespace="http://localhost:56040/Service1">
<Parameters>
<Parameter Name="textToHTML">1</Parameter>
</Parameters>
</Method>
<SoapAction>
http://localhost:56040/Service1/IService1/GernrateImagefromHtml
</SoapAction>
</Query>


The catch part is here namespace and SOAP action URL. If not configured properly then you have to invest lot of effort to find out any error.

  •   Now as in first approach we’ll have filed with binary Data that have to be mapped with Image control with same steps
Using Custom Code in SSRS itself
In SSRS we can write custom code using VB.net. For this approach I have created a class library in vb.net named “Html2ImageLib” its does same convert HTML data into Image and return as byte array.  
To use any external assembly into SSRS we have to register that into GAC with strong same and AllowPartiallyTrustedCallers settings.
  •   When ready with assembly then we have to add reference of that into RDL file. For that we have to click on report properties on body of report as follows
  •  In report properties add reference to your external assembly as follows:

 
  •  When add reference you need to provide class and instance name as follows:

  • In above screenshot Html2Image is class name in external assembly and I want SSRS to refer that class by txt2Image object.
  • Then we have add custom code to call our external assembly

  •   Next we have to set Image properties as follows
                  Data source:  Database
                  MIME Type:  Image/bmp
                  Value: will be an expression as follows




When all done then we are good to go… By using last approach we’ll have more control over code. But sometimes we get security exception when referring external assembly. 

[rsRuntimeErrorInExpression] The Value expression for the image ‘Image2’ contains an error: That assembly does not allow partially trusted callers.
[rsRuntimeErrorInExpression] The Value expression for the image ‘Image2’ contains an error: Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
[rsInvalidExternalImageProperty] The value of the ImageData property for the image ‘Image2’ is “”, which is not a valid ImageData.
Preview complete -- 0 errors, 2 warnings


That can be removed by configuring “rsreportserver.config”. In my case this setting didn’t worked; and I’m not sure of the reason. When searched more found I need to add security rights into external assembly by using following lines
   Dim securityPermission As New SecurityPermission(PermissionState.Unrestricted)
        securityPermission.Assert()

All Set… Using above approaches we can extend HTML support in SSRS. In my case client has preferred service based approach.  Let me know if you have any question .



Courtesy: Random Web Images, MSDN, Several online resources