Monday, November 1, 2010

Consuming Reporting Services 2005 Web Service

Reporting Service 2005 Web Service is a very useful API that lets do many tasks programmatically  such as rendering reports, uploading them, creating folders, setting properties etc.

In here I will try to show a brief tutorial on how to write a simple client that uses the SSRS 2005 Web Services. I assume you're using VS2008. The main point of this post is that when working Reporting Services 2005, you have to add a Web Service reference and NOT a Service reference. Doing so will alleviate you from having to apply the work-around shown here http://alsaydi.blogspot.com/2009/01/using-report-services-2005-web-service.html 

-- Create your project and start adding the references to the Reporting Services Web Services (ReportExecution and ReportService)
  1. Right click on your project References and select Add Service Reference the following dialg box show come up:


Now hold on. Click on Advanced because what we're trying to add is a Web Service Reference and not a Service Reference. Clicking on advanced gets you the below


Now for compatibility's sake, you have to click on "Add Web Reference ..." button  to get the below dialog box


and in the above dialog, you can now enter the URL for asmx file normally something like

http://ReportingServices_ServerName_Here/ReportServer/ReportService2005.asmx


The service you just added in the above steps will enable your project to call the Web Service to do things such as managing folder, listing reports, setting properties etc. To be able to render reports you need to add the Reporting Service Execution reference which you can do by repeating the above steps but use the URL below instead
 http://ReportingServices_ServerName_Here/ReportServer/ReportExecution2005.asmx

Now your project should be able to use the generated proxy classes to make calls against the reporting services Web Service API. There are some classes that have the same name in ReportingServices namespace and in the ReportingExecution for this reason you'll have to fully qualify your classes when you instantiate; otherwise you get "class name is ambiguous reference between ReportService2005 and ReportExecution2005". Sample code below will illustrate


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ReportingServicesClient.ReportExecution2005;
using ReportingServicesClient.ReportService2005 ;
using System.Web.Services.Protocols;
namespace ReportingServicesClient
{
    
    public class RS2005Client
    {
        private ReportingService2005 rs = null;
        private ReportExecutionService rsExec = null;
        private readonly string htmlformat = "HTML4.0";
        private readonly string excelformat = "EXCEL";
        private readonly string xmlformat = "XML";
        public RS2005Client()
        {
            rs = new ReportingService2005();
            rsExec = new ReportExecutionService();
            rs.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            rsExec.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            
        }
        public byte[] RenderReport(string path,ReportFormat frmt)
        {
            string format = null;
            switch (frmt)
            {
                case ReportFormat.HTML:
                    format = htmlformat;
                    break;
                case ReportFormat.Excel:
                    format = excelformat;
                    break;
                case ReportFormat.XML :
                    format = xmlformat;
                    break;
                default:
                    throw new Exception("RenderReport: invalid format supplied");
                    break;
            }
            return RenderReport(path, format);
        }
        private byte[] RenderReport(string path,string format)
        {
            byte[] result = null;
            string reportPath = path;// "/Cosmetic Tracking/Events";
            string historyID = null;
            string devInfo = @"False";
            #region parameters
            // Prepare report parameter.
            /*ParameterValue[] parameters = new ParameterValue[3];
            parameters[0] = new ParameterValue();
            parameters[0].Name = "EmpID";
            parameters[0].Value = "288";
            parameters[1] = new ParameterValue();
            parameters[1].Name = "ReportMonth";
            parameters[1].Value = "6"; // June
            parameters[2] = new ParameterValue();
            parameters[2].Name = "ReportYear";
            parameters[2].Value = "2004";*/
            #endregion                        
            string encoding;
            string mimeType;
            string extension;
            ReportExecution2005.Warning[] warnings = null;
            ReportExecution2005.ParameterValue[] reportHistoryParameters = new ReportExecution2005.ParameterValue[1];
            string[] streamIDs = null;
            ExecutionInfo execInfo = new ExecutionInfo();


            ExecutionHeader execHeader = new ExecutionHeader();
            rsExec.ExecutionHeaderValue = execHeader;
            execInfo = rsExec.LoadReport(reportPath, historyID);

            //rs.SetExecutionParameters(parameters, "en-us"); 
            try
            {
                //rsExec.SetExecutionParameters(reportHistoryParameters,"US-en");                
                result = rsExec.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
                            
            }
            catch (SoapException e)
            {
                throw e;                
            }
            return result;
        }
    }

    public enum ReportFormat
    {
        HTML
        ,Excel
        ,XML
    }
}

2 comments:

  1. Implementando este codigo detecte este error

    Error con el XML que faltaban etiquetas de cierre eso es por esta variable que tenemos que ponerla en formato XML quedaria asi

    string devInfo = @"False";

    string devInfo = @" False ";

    ReplyDelete
    Replies
    1. string devInfo = @" < DeviceInfo >< Toolbar >False<
      /DeviceInfo > ";

      Puse espacios porque al parecer la pagina interpreta el codigo y quita la etiqueta

      Delete