Upload SSRS report to all subfolders

by Ewald Hofman 15. June 2009 16:50

When you develop a new report for TFS and you want to deploy the report to all team projects, you have to do a lot of work to upload the file and to set the datasources.

This post uses TFS 2008 and SQL Server 2005

There is an easy way to automate that.

1. Add the web service to Reporting Service

Add a new web reference to the project. The url of the web service is http://<servername>/ReportServer/ReportService2005.asmx?wsdl

2. Add the library to upload the file

using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml;
using UploadLibrary.ReportService2005;
namespace UploadLibrary
{
    public class Report
    {
        public Report(string[] localFiles)
        {
            LocalFiles = localFiles;
        }
        public string[] LocalFiles { get; set; }
        public void Upload()
        {
            foreach (var subFolder in SubFolders())
            {
                foreach (var localFile in LocalFiles)
                {
                    Upload(subFolder, localFile);
                }
            }
        }
        private void Upload(string subFolder, string file)
        {
            var fi = new FileInfo(file);
            string reportName = fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length);
            string reportPath = "/" + subFolder + "/" + reportName;
            var rs = new ReportingService2005 { Credentials = CredentialCache.DefaultCredentials };
            //Read the file from the file system
            FileStream stream = File.OpenRead(file);
            var bytes = new byte[stream.Length];
            stream.Read(bytes, 0, (int)stream.Length);
            stream.Close();
            //Search for an exiting item in the subfolders (recursively)
            CatalogItem[] items = rs.FindItems("/" + subFolder,
            BooleanOperatorEnum.And,
            new[]
{
new SearchCondition
{
Name = "Name",
Condition = ConditionEnum.Equals,
Value = reportName
}
});
            // Only add the report in the current subfolder
            if (items.Count(c => c.Path == reportPath) > 0)
            {
                //Report exists -> update the report
                rs.SetReportDefinition(reportPath, bytes);
            }
            else
            {
                //Report does not exist -> create a new report
                rs.CreateReport(reportName, "/" + subFolder, false, bytes, new Property[0]);
            }
            //Relocate the datasources to the parent folder
            rs.SetItemDataSources(reportPath, UsedDatasources(file));
        }
        private static string[] SubFolders()
        {
            var rs = new ReportingService2005 { Credentials = CredentialCache.DefaultCredentials };
            var items = rs.ListChildren("/", false);
            return items.Where(i => i.Type == ItemTypeEnum.Folder).Select(i => i.Name).ToArray();
        }
        /// <summary>
        /// Returns an array of all datasources that are in use by the report.
        /// </summary>
        private DataSource[] UsedDatasources(string file)
        {
            var datasources = new Collection<DataSource>();
            // Read the rdl file
            var doc = new XmlDocument();
            doc.Load(file);
            var nsmgr = new XmlNamespaceManager(doc.NameTable);
            nsmgr.AddNamespace("rdl", "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition");
            // Go to the datasources node in the rdl file
            var nodes = doc.SelectNodes("rdl:Report/rdl:DataSources/rdl:DataSource", nsmgr);
            if (nodes != null)
            {
                // Iterate through the datasources in the rdl file
                foreach (XmlNode node in nodes)
                {
                    // Read the name of the datasource
                    var datasourceName = node.Attributes["Name"].InnerText;
                    // Add it to the result
                    datasources.Add(new DataSource
                    {
                        Item = new DataSourceReference { Reference = "/" + datasourceName },
                        Name = datasourceName
                    });
                }
            }
            // Return the result
            return datasources.ToArray();
        }
    }
}

3. Add any UI you like

You can add a winform project to your solution. On the form add a button called uploadReport and a textbox called fileName

private void uploadReport_Click(object sender, EventArgs e)
{
    Cursor = Cursors.WaitCursor;
    try
    {
        //Validation
        if (!File.Exists(fileName.Text))
        {
            MessageBox.Show(this, "Invalid filename", "Validation", MessageBoxButtons.OK,
            MessageBoxIcon.Error);
            return;
        }
        //Start upload
        var rpt = new Report(new string[] { fileName.Text });
        rpt.Upload();
        //Successful upload.
        MessageBox.Show(this, "The report is uploaded to all folders on the server!", "Successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch (Exception ex)
    {
        MessageBox.Show(this, ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    finally
    {
        Cursor = Cursors.Default;
    }
}

Tags:

Reporting

Comments

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

About the author

 

Ewald Hofman is MVP VS ALM and consultant at Avanade. His specialization is Application Lifecycle Management solutions based on Visual Studio ALM.

 

 

ClusterMap

Statistics

Statistics created at 09 Sep 2009

72 posts
43 comments
27 raters
24918 visit (136 per day)
6 users online