Share via


Automating Report Deployment with Reporting Services in SharePoint Integration Mode

Automating Report Deployment in Reporting Services can be challenging.  SharePoint offers many modes of deployment of files.  Unfortunately the out of the box deployment for SharePoint does not allow for automatic hook up of data sources.  So you can deploy the rdl's using SPFile upload functions on the SPWeb of your choice but those rdls will exist without data sources.  Here are the steps you will need to follow to deploy the reports automatically

1. Create the document library

2. Activate the Report Server Feature - no example but you'll need to check using something like SPContext.Current.Site.Features["367B94A9-4A15-42BA-B4A2-32420363E018"] != null

3.  Add the reporting services content type to the document libraries

4. Add the data sources

5. Add the reports

6. Associate the data sources with the reports

Here is my report manager that is an excellent example of being able to add reports dynamically from the file system.  In order to upload the report you'll need to call the ReportingServices2006 web service.  The reports manager is accessed by the Feature Activator on a custom feature just to give you an idea of how you might drive this.  The entry method is Deploy.

class RSHelper
    {
        public const string DOCLIBRARYNAME = "SomeLibrary";

        string dataSourceName = "somedatasource" ;
        ReportingService2006 rs;
        string libraryUrl;
        string path;
        SPWeb web;

  public void Deploy(string path, SPWeb web)
        {
            this.path = path;
            this.web = web;
            this.libraryUrl = string.Format("{0}/{1}/", web.Url, DOCLIBRARYNAME);
            rs = new ReportingService2006();
            rs.Url = web.Site.Url + "/_vti_bin/ReportServer/ReportService2006.asmx";

            rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
            CreateReportsLibrary();
            AddDataSourceToLibrary();
            AddReportToLibrary();
        }

       private  void CreateReportsLibrary()
        {
            Guid guid;

            SPDocumentLibrary list = null;
            //Not good practice but dictionary throws an exception when item not there.
            foreach (object o in web.Lists)
            {
                SPDocumentLibrary tempLib = o as SPDocumentLibrary;
                if (tempLib != null && tempLib.Title == DOCLIBRARYNAME)
                {
                    list = tempLib;
                    break;
                }
            }

            if (list == null)
            {
                guid = web.Lists.Add(DOCLIBRARYNAME, "", SPListTemplateType.DocumentLibrary);
                list = web.Lists[guid] as SPDocumentLibrary;
            }

//Add RS Content Types 
            (list).ContentTypesEnabled = true;
            SPContentTypeId id;
            SPContentType contentType;
            id = new SPContentTypeId("0x010100C3676CDFA2F24E1D949A8BF2B06F6B8B");//rdl
            contentType = web.AvailableContentTypes[id];
            if (list.ContentTypes[contentType.Name] == null)
            {
                (list).ContentTypes.Add(contentType);
            }
            id = new SPContentTypeId("0x0101007DFDDF56F8A9492DAA9366B83A95B3A0");//rsds
            contentType = web.AvailableContentTypes[id];
            if (list.ContentTypes[contentType.Name] == null)
            {
                list.ContentTypes.Add(contentType);
            }
            id = new SPContentTypeId("0x010100D8704AF8ED734F4088724751E0F2727D");//model
            contentType = web.AvailableContentTypes[id];
            if (list.ContentTypes[contentType.Name] == null)
            {
                (list).ContentTypes.Add(contentType);
            }
        }

        private void AddDataSourceToLibrary()
        {
            DataSourceDefinition dsd = new DataSourceDefinition();
            dsd.CredentialRetrieval = CredentialRetrievalEnum.None;
            dsd.ConnectString = "data source=.;initial catalog=someDB;Trusted_Connection=true";
            dsd.Enabled = true;
            dsd.EnabledSpecified = true;
            dsd.Extension = "SQL";
            dsd.ImpersonateUserSpecified = false;
            //Use the default prompt string.
            dsd.Prompt = null;
            dsd.WindowsCredentials = false;
            rs.CreateDataSource(dataSourceName+".rsds", libraryUrl, true, dsd, null);

        }

        private void AddReportToLibrary()
        {
            Byte[] definition = null;
            Warning[] warnings = null;
            string[] files = Directory.GetFiles(path);
            foreach (string file in files)
            {
                FileStream stream = File.OpenRead(file);
                definition = new Byte[stream.Length];
                stream.Read(definition, 0, (int)stream.Length);
                stream.Close();
                string filename = file.Replace(path, "");
                string parent = libraryUrl;
                if (file.Contains("rdl"))
                {
                    CatalogItem report = rs.CreateReport(filename, parent,
                                true, definition, null, out warnings);
                    AddDataSource(report);
                }
                else
                {
                    string mime = "image/gif";
                    CatalogItem report = rs.CreateResource(filename, parent,
                             true, definition, mime, null);
                }
                if (warnings != null)
                {
                    foreach (Warning warning in warnings)
                    {
                        Logger.Log(warning.Message);
                    }
                }
                else
                    Logger.Log(string.Format("Report: {0} created successfully " +
                                      " with no warnings", file));
            }

        }

        private void AddDataSource(CatalogItem report)
        {
            DataSourceReference reference = new DataSourceReference();
            reference.Reference = string.Format("{0}{1}.rsds",libraryUrl,dataSourceName);
            DataSource ds = new DataSource();
            ds.Item = reference;
            ds.Name = dataSourceName;
            rs.SetItemDataSources(report.Path, new DataSource[] { ds });
        }
    }

Comments

  • Anonymous
    January 31, 2008
    The comment has been removed

  • Anonymous
    April 30, 2008
    Its probably because your report is pointing to a datasource that doesn't exist yet.  You need to make sure that DataSource1 is already created before you setitemdatasources

  • Anonymous
    June 16, 2008
    Shawn Would it be possible for you to post a solution/ .cs file  featuring this code on this site. I am unsure of the using statements required and any references needed regards owain

  • Anonymous
    June 16, 2008
    Shawn, further to my earlier comment. These are my error messages. The type or namespace name 'ReportingService2006' could not be found (are you missing a using directive or an assembly reference?) The type or namespace name 'SPWeb' could not be found (are you missing a using directive or an assembly reference?) The type or namespace name 'CatalogItem' could not be found (are you missing a using directive or an assembly reference?) owain

  • Anonymous
    June 17, 2008
    I had made a previous post with a small code sample on how to upload report deployment. Now I'm improving

  • Anonymous
    June 17, 2008
    I added a new post with sample code, please check that out, its automated based on an xml file.  Let me know if you have any issues. please comment with your questions.

  • Anonymous
    June 04, 2009
    I was unable to upload reports when using Forms based authentication.  How would you pass the FBA credentials in using the code? Any help is appreciated. rs.Credentials = System.Net.CredentialCache.DefaultCredentials;

  • Anonymous
    June 04, 2009
    That sounds like a tough one.  I would say use a second alternate access mapping but sharepoint ssrs integration doesn't support two aam's.  Have you looked at this article http://msdn.microsoft.com/en-us/library/bb975135.aspx

  • Anonymous
    June 11, 2009
    Using the Authentication web service did the trick!  Thanks for the help!

  • Anonymous
    July 18, 2009
    I encountered the same DataSourceNotFoundException. The solution for me was by using the ReportServer.GetItemDataSources method on the report you are trying to hook up to the datasource file. It returns all the datasources referenced by the report. Go through the DataSources with invalid references (InvalidDataSourceReference) and fix them by setting the correct reference to the datasource file in each datasource. Here is the example private void AddDataSource(CatalogItem report, string dataSourceFileName)        {            DataSource[] referencedDataSources = rsClient.GetItemDataSources(report.Path);            foreach (DataSource dataSource in referencedDataSources)            {                //Fix Invalid references to the DataSource of the Report.                if (dataSource.Item.GetType().ToString() == typeof(InvalidDataSourceReference).ToString())                {                    DataSourceReference reference = new DataSourceReference();                    reference.Reference = string.Format("{0}/{1}", docLibraryUrl, dataSourceFileName);                    dataSource.Item = reference;                }            }            rsClient.SetItemDataSources(report.Path, referencedDataSources);        }

  • Anonymous
    April 27, 2012
    The comment has been removed