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:
- {
- public CustomCache()
- {
- documentStorage = new Dictionary<string, object>();
- pagesStorage = new Dictionary<string, object>();
- }
- Dictionary<string, object> documentStorage;
- Dictionary<string, object> pagesStorage;
- public void AddDocumentToCache(string key, PerpetuumSoft.Reporting.DOM.Document value, params object[] parameters)
- {
- documentStorage.Add(key, value);
- }
- public void AddPageToCache(string key, PerpetuumSoft.Reporting.WebViewer.Model.PageInfoModel value, params object[] parameters)
- {
- if (!pagesStorage.ContainsKey(key))
- {
- pagesStorage.Add(key, value);
- }
- else
- {
- pagesStorage[key] = value;
- }
- }
- public object GetDocumentFromCache(string key)
- {
- return documentStorage[key];
- }
- public object GetPageFromCache(string key)
- {
- if (!pagesStorage.ContainsKey(key))
- {
- return null;
- }
- return pagesStorage[key];
- }
- }
8) Open ReportService1.cs code and override CreateCache method of the ReportService1 class
- protected override PerpetuumSoft.Reporting.WebViewer.Server.Cache.IReportCache CreateCache()
- {
- return new CustomCache();
- }
9) Right click on ReportService1.cs and select “View Designer”.
10) Add report to reportManager and call it “slot”
11) Open App.config and configure service as follows:
- <?xml version=“1.0″ encoding=“utf-8″ ?>
- <configuration>
- <configSections>
- <section name=“PerpetuumSoftServices”
- type=
- ”PerpetuumSoft.Reporting.WebViewer.Server.ServicesConfigurationSection,
- PerpetuumSoft.Reporting.WebViewer.Server”
- allowLocation=“true” allowDefinition=“Everywhere”/>
- </configSections>
- <PerpetuumSoftServices>
- <ReportServiceURL value=“http://localhost:8000/ReportService1″/>
- </PerpetuumSoftServices> <!–Configures Get requests URL –>
- <system.serviceModel>
- <behaviors>
- <serviceBehaviors>
- <behavior name=“ReportService1Behavior”>
- <serviceMetadata httpGetEnabled=“true” httpGetUrl=“http://localhost:8000/ReportService1″/>
- <serviceDebug includeExceptionDetailInFaults=“true” />
- </behavior>
- </serviceBehaviors>
- <endpointBehaviors>
- <behavior name=“ReportService1BehaviourConfiguration”>
- <enableWebScript/>
- </behavior>
- </endpointBehaviors>
- </behaviors>
- <serviceHostingEnvironment multipleSiteBindingsEnabled=“true” aspNetCompatibilityEnabled=“true” />
- <services>
- <service name=“WCFHoster.ReportService1″ behaviorConfiguration=“ReportService1Behavior”>
- <endpoint address=“http://localhost:8000/ReportService1″ binding=“webHttpBinding” contract=“PerpetuumSoft.Reporting.WebViewer.Server.IReportService” behaviorConfiguration=“ReportService1BehaviourConfiguration”/> <!–Report Service endpoint config –>
- <endpoint address=“http://localhost:8080/ReportService1/mex” binding =“mexHttpBinding” bindingConfiguration=“” contract=“IMetadataExchange”/> <!–MetaDataExchange endpoint config –> </service>
- </services>
- </system.serviceModel>
- </configuration>
13) Run Console Application and wait until service is started:
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:
- <!DOCTYPE html>
- <html xmlns=“http://www.w3.org/1999/xhtml”>
- <head>
- <title></title>
- <link href=“Styles/ReportViewer.css” rel=“stylesheet” type=“text/css” />
- <link href=“Styles/WebViewerSkin.css” rel=“stylesheet” type=“text/css” />
- <link href=“Styles/themes/base/jquery.ui.all.css” rel=“stylesheet” type=“text/css” />
- </head>
- <body>
- <script src=“Scripts/jquery-1.5.1.js” type=“text/javascript”></script>
- <script src=“Scripts/jquery-ui-1.8.11.js” type=“text/javascript”></script>
- <script src=“Scripts/jquery.treeview.js” type=“text/javascript”></script>
- <script src=“Scripts/mscorlib.js” type=“text/javascript”></script>
- <script src=“Scripts/PerpetuumSoft.Reporting.WebViewer.Client.Model.js” type=“text/javascript”></script>
- <script src=“Scripts/PerpetuumSoft.Reporting.WebViewer.Client.js” type=“text/javascript”></script>
- <script src=“Scripts/WebViewer.Style.js” type=“text/javascript”></script>
- <script src=“Scripts/json2.js” type=“text/javascript”></script>
- <script type=“text/javascript”>
- var reportViewer = null;
- $(document).ready(function () {
- Initialize();
- InitializeReportViewer();
- });
- function HideUnsupportedFeatures() {
- if (reportViewer != null && !reportViewer.supportZoom()) {
- $(“#ssr_zoomInButton”).css(“display”, ”none”);
- $(“#ssr_zoomOutButton”).css(“display”, ”none”);
- }
- }
- function InitializeReportViewer() {
- jQuery.support.cors = true;<!– Force jquery to support cross domain requests–>
- var strategy = new PerpetuumSoft.Reporting.WebViewer.Client.WebKitBrowsersStrategy();
- var browserInfo = new PerpetuumSoft.Reporting.WebViewer.Client.BrowserInfo();
- browserInfo.browserName = PerpetuumSoft.Reporting.WebViewer.Client.BrowserInfo.BROWSER_SAFARI;
- browserInfo.version = ’14.0.0.0′;
- PerpetuumSoft.Reporting.WebViewer.Client.BrowserStrategy.browserStrategies.addStrategy(browserInfo, strategy);
- var strategy = new PerpetuumSoft.Reporting.WebViewer.Client.UnsupportedBrowserStrategy();
- var browserInfo = new PerpetuumSoft.Reporting.WebViewer.Client.BrowserInfo();
- browserInfo.browserName = PerpetuumSoft.Reporting.WebViewer.Client.BrowserInfo.BROWSER_OPERA;
- browserInfo.version = ’11.0.0.0′;
- PerpetuumSoft.Reporting.WebViewer.Client.BrowserStrategy.browserStrategies.addStrategy(browserInfo, strategy);
- reportViewer = new PerpetuumSoft.Reporting.WebViewer.Client.ReportViewer(‘#ssr_reportContent’);
- HideUnsupportedFeatures();
- reportViewer.setServiceUrl(“http://localhost:8000/ReportService1″); <!–Put your service URL here–>
- reportViewer.reportName = “slot”;<!–Specify report name–>
- reportViewer.setDocumentMapControl(“#ssr_documentMapContentPanel”);
- reportViewer.setThumbnailsControl(“#ssr_thumbnailContentPanel”);
- reportViewer.documentInfoLoadedEvent = function (pages) {
- EnableToolbarState();
- if (pages.length > 1) {
- pageCount = pages.length;
- EnableNextLastPage();
- DisablePreviousFirstPage();
- }
- else {
- DisableNextLastPage();
- DisablePreviousFirstPage();
- }
- $(“#ssr_pageCountBox”).text(pages.length.toString());
- reportViewer.loadThumbnails();
- };
- reportViewer.errorEvent = function (errorModel) {
- switch (errorModel.errorType) {
- case PerpetuumSoft.Reporting.WebViewer.Client.ErrorType.communicationError:
- console.log(errorModel.error._error$1);
- break;
- case PerpetuumSoft.Reporting.WebViewer.Client.ErrorType.clientError:
- console.log(“clientError” + (errorModel.error).message);
- break;
- case PerpetuumSoft.Reporting.WebViewer.Client.ErrorType.serverError:
- console.log(“serverError” + (errorModel.error).message + (errorModel.error).getInformation());
- break;
- default:
- console.log(errorModel.error.message);
- break;
- }
- //EnableErrorButton();
- //ShowErrorDialog();
- };
- reportViewer.currentPageChangedEvent = function (pageNumber) {
- if (reportViewer.isFirstPage()) {
- DisablePreviousFirstPage();
- }
- else {
- EnablePreviousFirstPage();
- }
- if (reportViewer.isLastPage()) {
- DisableNextLastPage();
- }
- else {
- EnableNextLastPage();
- }
- $(“#ssr_currentPageNumberBox”).val(pageNumber.toString());
- };
- reportViewer.renderDocument();
- }
- </script>
- <div class=“ssr_reportViewerControl”>
- <!–Toolbar panel, contains print and exports button–>
- <div id=“ssr_toolBarPanel” class=“ssr_toolBar”>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_printButton” class=“ssr_toolButton ssr_printButtonDisable” title=“Print”>
- </div>
- </div>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_rtfExportButton” class=“ssr_toolButton ssr_rtfButtonDisable” title=“Export to Rtf”>
- </div>
- </div>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_pdfExportButton” class=“ssr_toolButton ssr_pdfButtonDisable” title=“Export to Pdf”>
- </div>
- </div>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_excelExportButton” class=“ssr_toolButton ssr_excelButtonDisable” title=“Export to Excel”>
- </div>
- </div>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_htmlExportButton” class=“ssr_toolButton ssr_htmlButtonDisable” title=“Export to Html”>
- </div>
- </div>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_xpsExportButton” class=“ssr_toolButton ssr_xpsButtonDisable” title=“Export to Xps”>
- </div>
- </div>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_xlsxExportButton” class=“ssr_toolButton ssr_xlsxButtonDisable” title=“Export to OpenXml Excel”>
- </div>
- </div>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_zoomInButton” class=“ssr_toolButton ssr_zoomInButtonDisable” title=“Zoom in”>
- </div>
- </div>
- <div class=“ssr_toolButtonContainer”>
- <div id=“ssr_zoomOutButton” class=“ssr_toolButton ssr_zoomOutButtonDisable” title=“Zoom out”>
- </div>
- </div>
- </div>
- <div class=“ssr_centralDiv”>
- <!–Contains thumbnails and documentMap elements–>
- <div class=“ssr_navigationArea” id=“ssr_navigationAreaElement”>
- <div class=“ssr_navigationIconPanel” id=“ssr_navigationIconPanel”>
- <div class=“ssr_thumbnailButtonContainer” id=“ssr_thumbnailButtonContainer”>
- <!–shows or hides thumbnail element–>
- <div title=“Thumbnails” id=“ssr_thumbnailButton” class=“ssr_thumbnailButton ssr_thumbnailButtonDisable”>
- </div>
- </div>
- <div class=“ssr_documentMapButtonContainer” id=“ssr_documentMapButtonContainer”>
- <!–shows or hides document map element–>
- <div title=“Document Map” id=“ssr_documentMapButton” class=“ssr_documentMapButton ssr_documentMapButtonDisable”>
- </div>
- </div>
- </div>
- <div id=“ssr_thumbnailsPanel” class=“ssr_thumbnailsPanel”>
- <div id=“ssr_thumbnailHeadPanel” class=“ssr_thumbnailHeadPanel”>
- <span class=“ssr_thumbnailHeadPanelTitle”>Thumbnails</span>
- <div title=“Close” id=“ssr_closeThumbnailPanelButton” class=“ssr_closeThumbnailPanelButton”>
- </div>
- </div>
- <div id=“ssr_wrapThumbnailContentPanel” class=“ssr_wrapThumbnailContentPanel”>
- <!–element which contains a list of thumbnail–>
- <div id=“ssr_thumbnailContentPanel” class=“ssr_thumbnailContentPanel”>
- </div>
- </div>
- </div>
- <div id=“ssr_documentMapPanel” class=“ssr_documentMapPanel”>
- <div id=“ssr_documentMapHeadPanel” class=“ssr_documentMapHeadPanel”>
- <span class=“ssr_documentMapHeadPanelTitle”>Document Map</span>
- <div title=“Close” id=“ssr_closeDocumentMapPanelButton” class=“ssr_closeThumbnailPanelButton”>
- </div>
- </div>
- <div id=“ssr_wrapDocumentMapContentPanel” class=“ssr_wrapDocumentMapContentPanel”>
- <!–element which contains a document map–>
- <div id=“ssr_documentMapContentPanel” class=“ssr_documentMapContentPanel”>
- </div>
- </div>
- </div>
- </div>
- <!–reports will be shows in this element–>
- <div id=“ssr_reportContent” class=“ssr_reportArea”>
- </div>
- </div>
- <!–Statusbar panel–>
- <div id=“ssr_statusBarPanel” class=“ssr_statusPanel”>
- <div id=“ssr_paginationPanel” class=“ssr_paginationPanel”>
- <div class=“ssr_statusButtonContainer ssr_statusButtonContainerBack”>
- <div id=“ssr_firstPageButton” class=“ssr_statusButton ssr_statusButtonBack ssr_firstPageDisable”>
- </div>
- </div>
- <div class=“ssr_statusButtonContainer ssr_statusButtonContainerBack”>
- <div id=“ssr_previousPageButton” class=“ssr_statusButton ssr_statusButtonBack ssr_previousPageDisable”>
- </div>
- </div>
- <div class=“ssr_statusCurrentPageContainer”>
- <!–displays the current page number–>
- <input id=“ssr_currentPageNumberBox” class=“ssr_currentPageNumber” title=“Current page” />
- <span class=“ssr_pageCountOf”>of</span><span> </span><span id=“ssr_pageCountBox”
- class=“ssr_pageCount”>0</span>
- </div>
- <div class=“ssr_statusButtonContainer ssr_statusButtonContainerForward”>
- <div id=“ssr_nextPageButton” class=“ssr_statusButton ssr_statusButtonForward ssr_nextPageDisable”>
- </div>
- </div>
- <div class=“ssr_statusButtonContainer ssr_statusButtonContainerForward”>
- <div id=“ssr_lastPageButton” class=“ssr_statusButton ssr_statusButtonForward ssr_lastPageDisable”>
- </div>
- </div>
- </div>
- <!–Shows or hides error dialog–>
- <div id=“ssr_notificationPanel” class=“ssr_notificationPanel”>
- <div id=“ssr_errorButton” class=“ssr_errorButton ssr_errorButtonDisable”>
- </div>
- </div>
- </div>
- </div>
- <div id=“ssr_errorDialog” title=“Error information” style=“display: none;”>
- <div id=“ssr_errorMessage” class=“ssr_errorMessageContent”>
- </div>
- </div>
- </body>
- </html>
5) Type in the full path to in your browser address line and enjoy the result.
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