How to configure a WebViewer without IIS

Vitaliy Korney

This article displays the possibility of hosting a WCF service in a console application without using Internet Information Services.

To begin with, let’s create our console application. In MS Visual Studio we create a console application project and add a Report Service Over Http item to it.

1)      Visual C# items->SharpShooter Reports->Web->Report Service Over Http (Web)

2)      Call this service a “ReportService1”.

3)      Rename “ReportService1Imp.cs” to “ReportService1.cs”.

4)      Open SVC markup and change service attribute accordingly to <namespace>. ReportService1

5)      Rename ReportService1 class name as well.

6)      Delete AspNetCompatibilityRequirements attribute.

7)      Implement your own document storage. For example like shown in the code below:
 

  1. {  
  2. public CustomCache()  
  3. {  
  4. documentStorage = new Dictionary<string, object>();  
  5. pagesStorage = new Dictionary<string, object>();  
  6. }  
  7. Dictionary<string, object> documentStorage;  
  8. Dictionary<string, object> pagesStorage;  
  9.    
  10. public void AddDocumentToCache(string key, PerpetuumSoft.Reporting.DOM.Document value, params object[] parameters)  
  11. {  
  12. documentStorage.Add(key, value);  
  13. }  
  14.    
  15. public void AddPageToCache(string key, PerpetuumSoft.Reporting.WebViewer.Model.PageInfoModel value, params object[] parameters)  
  16. {  
  17. if (!pagesStorage.ContainsKey(key))  
  18. {  
  19. pagesStorage.Add(key, value);  
  20. }  
  21. else  
  22. {  
  23. pagesStorage[key] = value;  
  24. }  
  25. }  
  26.    
  27. public object GetDocumentFromCache(string key)  
  28. {  
  29. return documentStorage[key];  
  30. }  
  31.    
  32. public object GetPageFromCache(string key)  
  33. {  
  34. if (!pagesStorage.ContainsKey(key))  
  35. {  
  36. return null;  
  37. }  
  38. return pagesStorage[key];  
  39. }  
  40. }  

 
8)      Open ReportService1.cs code and override CreateCache method of the ReportService1 class

 

  1. protected override PerpetuumSoft.Reporting.WebViewer.Server.Cache.IReportCache CreateCache()  
  2. {  
  3. return new CustomCache();  
  4. }  

 

9)      Right click on ReportService1.cs  and select “View Designer”.
 
WCF_3
 
10)   Add report to reportManager and call it “slot”
 
WCF_4
 
11)   Open App.config and configure service as follows:
 

  1. <?xml version=“1.0″ encoding=“utf-8″ ?>  
  2. <configuration>  
  3.   <configSections>   
  4.     <section name=“PerpetuumSoftServices”   
  5.              type=  
  6.           ”PerpetuumSoft.Reporting.WebViewer.Server.ServicesConfigurationSection,   
  7.           PerpetuumSoft.Reporting.WebViewer.Server”   
  8.           allowLocation=“true” allowDefinition=“Everywhere”/>    
  9. </configSections>  
  10.   <PerpetuumSoftServices>  
  11.     <ReportServiceURL value=“http://localhost:8000/ReportService1″/>  
  12. </PerpetuumSoftServices> <!–Configures Get requests URL –>   
  13.   <system.serviceModel>  
  14.     <behaviors>  
  15.       <serviceBehaviors>  
  16.         <behavior name=“ReportService1Behavior”>  
  17.           <serviceMetadata httpGetEnabled=“true” httpGetUrl=“http://localhost:8000/ReportService1″/>  
  18.           <serviceDebug includeExceptionDetailInFaults=“true” />          
  19.         </behavior>  
  20.       </serviceBehaviors>  
  21.      <endpointBehaviors>  
  22.         <behavior name=“ReportService1BehaviourConfiguration”>  
  23.         <enableWebScript/>  
  24.         </behavior>  
  25.      </endpointBehaviors>  
  26.     </behaviors>  
  27.     <serviceHostingEnvironment multipleSiteBindingsEnabled=“true” aspNetCompatibilityEnabled=“true” />  
  28.     <services>  
  29.       <service name=“WCFHoster.ReportService1″ behaviorConfiguration=“ReportService1Behavior”>  
  30.         <endpoint address=“http://localhost:8000/ReportService1″ binding=“webHttpBinding” contract=“PerpetuumSoft.Reporting.WebViewer.Server.IReportService” behaviorConfiguration=“ReportService1BehaviourConfiguration”/> <!–Report Service endpoint config –>  
  31.         <endpoint address=“http://localhost:8080/ReportService1/mex” binding =“mexHttpBinding” bindingConfiguration=“” contract=“IMetadataExchange”/> <!–MetaDataExchange endpoint config –>      </service>  
  32.     </services>  
  33.   </system.serviceModel>  
  34. </configuration>  

 
13)   Run Console Application and wait until service is started:

 
WCF_5
 

Now we need to configure our client side application.
 
To do this:
 
1)      Open a new folder in which you want to create a client application.

2)      Open a folder with a WebViewer demo located under the following path (C:\Program Files (x86)\Perpetuum Software\SharpShooter Reports\Samples\SharpShooterReports.Web\SharpShooterWebViewerSkin\SharpShooterWebViewerSkin)

3)      Copy Scripts and Styles folder to your folder from it.

4)      Create HTML file and paste the following code inside:
 

  1. <!DOCTYPE html>  
  2. <html xmlns=“http://www.w3.org/1999/xhtml”>  
  3. <head>  
  4.     <title></title>  
  5.     <link href=“Styles/ReportViewer.css” rel=“stylesheet” type=“text/css” />  
  6.     <link href=“Styles/WebViewerSkin.css” rel=“stylesheet” type=“text/css” />  
  7.     <link href=“Styles/themes/base/jquery.ui.all.css” rel=“stylesheet” type=“text/css” />  
  8. </head>  
  9. <body>  
  10.     <script src=“Scripts/jquery-1.5.1.js” type=“text/javascript”></script>  
  11.     <script src=“Scripts/jquery-ui-1.8.11.js” type=“text/javascript”></script>  
  12.     <script src=“Scripts/jquery.treeview.js” type=“text/javascript”></script>  
  13.     <script src=“Scripts/mscorlib.js” type=“text/javascript”></script>  
  14.     <script src=“Scripts/PerpetuumSoft.Reporting.WebViewer.Client.Model.js” type=“text/javascript”></script>  
  15.     <script src=“Scripts/PerpetuumSoft.Reporting.WebViewer.Client.js” type=“text/javascript”></script>  
  16.     <script src=“Scripts/WebViewer.Style.js” type=“text/javascript”></script>  
  17.     <script src=“Scripts/json2.js” type=“text/javascript”></script>  
  18.   
  19.     <script type=“text/javascript”>  
  20.         var reportViewer = null;  
  21.   
  22.         $(document).ready(function () {  
  23.             Initialize();  
  24.             InitializeReportViewer();  
  25.         });  
  26.   
  27.         function HideUnsupportedFeatures() {  
  28.             if (reportViewer != null && !reportViewer.supportZoom()) {  
  29.                 $(“#ssr_zoomInButton”).css(“display”, ”none”);  
  30.                 $(“#ssr_zoomOutButton”).css(“display”, ”none”);  
  31.             }  
  32.         }  
  33.   
  34.         function InitializeReportViewer() {  
  35.             jQuery.support.cors = true;<!– Force jquery to support cross domain requests–>  
  36.             var strategy = new PerpetuumSoft.Reporting.WebViewer.Client.WebKitBrowsersStrategy();  
  37.             var browserInfo = new PerpetuumSoft.Reporting.WebViewer.Client.BrowserInfo();  
  38.             browserInfo.browserName = PerpetuumSoft.Reporting.WebViewer.Client.BrowserInfo.BROWSER_SAFARI;  
  39.             browserInfo.version = ’14.0.0.0′;  
  40.             PerpetuumSoft.Reporting.WebViewer.Client.BrowserStrategy.browserStrategies.addStrategy(browserInfo, strategy);  
  41.   
  42.             var strategy = new PerpetuumSoft.Reporting.WebViewer.Client.UnsupportedBrowserStrategy();  
  43.             var browserInfo = new PerpetuumSoft.Reporting.WebViewer.Client.BrowserInfo();  
  44.             browserInfo.browserName = PerpetuumSoft.Reporting.WebViewer.Client.BrowserInfo.BROWSER_OPERA;  
  45.             browserInfo.version = ’11.0.0.0′;  
  46.             PerpetuumSoft.Reporting.WebViewer.Client.BrowserStrategy.browserStrategies.addStrategy(browserInfo, strategy);  
  47.   
  48.   
  49.             reportViewer = new PerpetuumSoft.Reporting.WebViewer.Client.ReportViewer(‘#ssr_reportContent’);  
  50.   
  51.             HideUnsupportedFeatures();  
  52.   
  53.             reportViewer.setServiceUrl(“http://localhost:8000/ReportService1″); <!–Put your service URL here–>  
  54.             reportViewer.reportName = “slot”;<!–Specify report name–>  
  55.   
  56.             reportViewer.setDocumentMapControl(“#ssr_documentMapContentPanel”);  
  57.             reportViewer.setThumbnailsControl(“#ssr_thumbnailContentPanel”);  
  58.   
  59.             reportViewer.documentInfoLoadedEvent = function (pages) {  
  60.                 EnableToolbarState();  
  61.                 if (pages.length > 1) {  
  62.                     pageCount = pages.length;  
  63.                     EnableNextLastPage();  
  64.                     DisablePreviousFirstPage();  
  65.                 }  
  66.                 else {  
  67.                     DisableNextLastPage();  
  68.                     DisablePreviousFirstPage();  
  69.                 }  
  70.                 $(“#ssr_pageCountBox”).text(pages.length.toString());  
  71.                 reportViewer.loadThumbnails();  
  72.             };  
  73.   
  74.             reportViewer.errorEvent = function (errorModel) {  
  75.                 switch (errorModel.errorType) {  
  76.                     case PerpetuumSoft.Reporting.WebViewer.Client.ErrorType.communicationError:  
  77.                         console.log(errorModel.error._error$1);  
  78.                         break;  
  79.                     case PerpetuumSoft.Reporting.WebViewer.Client.ErrorType.clientError:  
  80.                         console.log(“clientError” + (errorModel.error).message);  
  81.                         break;  
  82.                     case PerpetuumSoft.Reporting.WebViewer.Client.ErrorType.serverError:  
  83.                         console.log(“serverError” + (errorModel.error).message + (errorModel.error).getInformation());  
  84.                         break;  
  85.                     default:  
  86.                         console.log(errorModel.error.message);  
  87.                         break;  
  88.                 }  
  89.                 //EnableErrorButton();  
  90.                 //ShowErrorDialog();  
  91.             };  
  92.   
  93.             reportViewer.currentPageChangedEvent = function (pageNumber) {  
  94.                 if (reportViewer.isFirstPage()) {  
  95.                     DisablePreviousFirstPage();  
  96.                 }  
  97.                 else {  
  98.                     EnablePreviousFirstPage();  
  99.                 }  
  100.                 if (reportViewer.isLastPage()) {  
  101.                     DisableNextLastPage();  
  102.                 }  
  103.                 else {  
  104.                     EnableNextLastPage();  
  105.                 }  
  106.                 $(“#ssr_currentPageNumberBox”).val(pageNumber.toString());  
  107.             };  
  108.   
  109.             reportViewer.renderDocument();  
  110.         }  
  111.   
  112.     </script>  
  113.   
  114.     <div class=“ssr_reportViewerControl”>  
  115.         <!–Toolbar panel, contains print and exports button–>  
  116.         <div id=“ssr_toolBarPanel” class=“ssr_toolBar”>  
  117.             <div class=“ssr_toolButtonContainer”>  
  118.                 <div id=“ssr_printButton” class=“ssr_toolButton ssr_printButtonDisable” title=“Print”>  
  119.                 </div>  
  120.             </div>  
  121.             <div class=“ssr_toolButtonContainer”>  
  122.                 <div id=“ssr_rtfExportButton” class=“ssr_toolButton ssr_rtfButtonDisable” title=“Export to Rtf”>  
  123.                 </div>  
  124.             </div>  
  125.             <div class=“ssr_toolButtonContainer”>  
  126.                 <div id=“ssr_pdfExportButton” class=“ssr_toolButton ssr_pdfButtonDisable” title=“Export to Pdf”>  
  127.                 </div>  
  128.             </div>  
  129.             <div class=“ssr_toolButtonContainer”>  
  130.                 <div id=“ssr_excelExportButton” class=“ssr_toolButton ssr_excelButtonDisable” title=“Export to Excel”>  
  131.                 </div>  
  132.             </div>  
  133.             <div class=“ssr_toolButtonContainer”>  
  134.                 <div id=“ssr_htmlExportButton” class=“ssr_toolButton ssr_htmlButtonDisable” title=“Export to Html”>  
  135.                 </div>  
  136.             </div>  
  137.             <div class=“ssr_toolButtonContainer”>  
  138.                 <div id=“ssr_xpsExportButton” class=“ssr_toolButton ssr_xpsButtonDisable” title=“Export to Xps”>  
  139.                 </div>  
  140.             </div>  
  141.             <div class=“ssr_toolButtonContainer”>  
  142.                 <div id=“ssr_xlsxExportButton” class=“ssr_toolButton ssr_xlsxButtonDisable” title=“Export to OpenXml Excel”>  
  143.                 </div>  
  144.             </div>  
  145.             <div class=“ssr_toolButtonContainer”>  
  146.                 <div id=“ssr_zoomInButton” class=“ssr_toolButton ssr_zoomInButtonDisable” title=“Zoom in”>  
  147.                 </div>  
  148.             </div>  
  149.             <div class=“ssr_toolButtonContainer”>  
  150.                 <div id=“ssr_zoomOutButton” class=“ssr_toolButton ssr_zoomOutButtonDisable” title=“Zoom out”>  
  151.                 </div>  
  152.             </div>  
  153.         </div>  
  154.         <div class=“ssr_centralDiv”>  
  155.             <!–Contains thumbnails and documentMap elements–>  
  156.             <div class=“ssr_navigationArea” id=“ssr_navigationAreaElement”>  
  157.                 <div class=“ssr_navigationIconPanel” id=“ssr_navigationIconPanel”>  
  158.                     <div class=“ssr_thumbnailButtonContainer” id=“ssr_thumbnailButtonContainer”>  
  159.                         <!–shows or hides thumbnail element–>  
  160.                         <div title=“Thumbnails” id=“ssr_thumbnailButton” class=“ssr_thumbnailButton ssr_thumbnailButtonDisable”>  
  161.                         </div>  
  162.                     </div>  
  163.                     <div class=“ssr_documentMapButtonContainer” id=“ssr_documentMapButtonContainer”>  
  164.                         <!–shows or hides document map element–>  
  165.                         <div title=“Document Map” id=“ssr_documentMapButton” class=“ssr_documentMapButton ssr_documentMapButtonDisable”>  
  166.                         </div>  
  167.                     </div>  
  168.                 </div>  
  169.                 <div id=“ssr_thumbnailsPanel” class=“ssr_thumbnailsPanel”>  
  170.                     <div id=“ssr_thumbnailHeadPanel” class=“ssr_thumbnailHeadPanel”>  
  171.                         <span class=“ssr_thumbnailHeadPanelTitle”>Thumbnails</span>  
  172.                         <div title=“Close” id=“ssr_closeThumbnailPanelButton” class=“ssr_closeThumbnailPanelButton”>  
  173.                         </div>  
  174.                     </div>  
  175.                     <div id=“ssr_wrapThumbnailContentPanel” class=“ssr_wrapThumbnailContentPanel”>  
  176.                         <!–element which contains a list of thumbnail–>  
  177.                         <div id=“ssr_thumbnailContentPanel” class=“ssr_thumbnailContentPanel”>  
  178.                         </div>  
  179.                     </div>  
  180.                 </div>  
  181.                 <div id=“ssr_documentMapPanel” class=“ssr_documentMapPanel”>  
  182.                     <div id=“ssr_documentMapHeadPanel” class=“ssr_documentMapHeadPanel”>  
  183.                         <span class=“ssr_documentMapHeadPanelTitle”>Document Map</span>  
  184.                         <div title=“Close” id=“ssr_closeDocumentMapPanelButton” class=“ssr_closeThumbnailPanelButton”>  
  185.                         </div>  
  186.                     </div>  
  187.                     <div id=“ssr_wrapDocumentMapContentPanel” class=“ssr_wrapDocumentMapContentPanel”>  
  188.                         <!–element which contains a document map–>  
  189.                         <div id=“ssr_documentMapContentPanel” class=“ssr_documentMapContentPanel”>  
  190.                         </div>  
  191.                     </div>  
  192.                 </div>  
  193.             </div>  
  194.             <!–reports will be shows in this element–>  
  195.             <div id=“ssr_reportContent” class=“ssr_reportArea”>  
  196.             </div>  
  197.         </div>  
  198.         <!–Statusbar panel–>  
  199.         <div id=“ssr_statusBarPanel” class=“ssr_statusPanel”>  
  200.             <div id=“ssr_paginationPanel” class=“ssr_paginationPanel”>  
  201.                 <div class=“ssr_statusButtonContainer ssr_statusButtonContainerBack”>  
  202.                     <div id=“ssr_firstPageButton” class=“ssr_statusButton ssr_statusButtonBack ssr_firstPageDisable”>  
  203.                     </div>  
  204.                 </div>  
  205.                 <div class=“ssr_statusButtonContainer ssr_statusButtonContainerBack”>  
  206.                     <div id=“ssr_previousPageButton” class=“ssr_statusButton ssr_statusButtonBack ssr_previousPageDisable”>  
  207.                     </div>  
  208.                 </div>  
  209.                 <div class=“ssr_statusCurrentPageContainer”>  
  210.                     <!–displays the current page number–>  
  211.                     <input id=“ssr_currentPageNumberBox” class=“ssr_currentPageNumber” title=“Current page” />  
  212.                     <span class=“ssr_pageCountOf”>of</span><span> </span><span id=“ssr_pageCountBox”  
  213.                         class=“ssr_pageCount”>0</span>  
  214.                 </div>  
  215.                 <div class=“ssr_statusButtonContainer ssr_statusButtonContainerForward”>  
  216.                     <div id=“ssr_nextPageButton” class=“ssr_statusButton ssr_statusButtonForward ssr_nextPageDisable”>  
  217.                     </div>  
  218.                 </div>  
  219.                 <div class=“ssr_statusButtonContainer ssr_statusButtonContainerForward”>  
  220.                     <div id=“ssr_lastPageButton” class=“ssr_statusButton ssr_statusButtonForward ssr_lastPageDisable”>  
  221.                     </div>  
  222.                 </div>  
  223.             </div>  
  224.             <!–Shows or hides error dialog–>  
  225.             <div id=“ssr_notificationPanel” class=“ssr_notificationPanel”>  
  226.                 <div id=“ssr_errorButton” class=“ssr_errorButton ssr_errorButtonDisable”>  
  227.                 </div>  
  228.             </div>  
  229.         </div>  
  230.     </div>  
  231.       
  232.     <div id=“ssr_errorDialog” title=“Error information” style=“display: none;”>  
  233.         <div id=“ssr_errorMessage” class=“ssr_errorMessageContent”>  
  234.         </div>  
  235.     </div>  
  236. </body>  
  237. </html>  

 

5)      Type in the full path to in your browser address line and enjoy the result.
 
WCF_6
 

 
6) Doesn’t work in other browsers because of domain restrictions? Have a look at the following article:
http://blogs.microsoft.co.il/blogs/idof/archive/2011/07/02/cross-origin-resource-sharing-cors-and-wcf.aspx

The sample containing both a server part and a client side application can be found under the link below.
 
Console sample

August 5th, 2013

Leave a Comment