
{"id":1261,"date":"2013-05-03T14:52:27","date_gmt":"2013-05-03T18:52:27","guid":{"rendered":"http:\/\/www.ikriv.com\/blog\/?p=1261"},"modified":"2013-05-03T14:52:27","modified_gmt":"2013-05-03T18:52:27","slug":"ssrs-production-deployment-part-3","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=1261","title":{"rendered":"SSRS Production Deployment, Part 3"},"content":{"rendered":"<p><b>Deploying Reports<\/b><\/p>\n<p><a href=\"http:\/\/www.ikriv.com\/dev\/misc\/ssrs\/Deploy.vb\">Download code<\/a>.<\/p>\n<p>In <a href=\"http:\/\/www.ikriv.com\/blog\/?p=1248\">Part 2<\/a> we talked about deploying SSRS data sources. Now we are ready reports.<\/p>\n<p>Reports are deployed using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/reportservice2005.reportingservice2005.createreport.aspx\">rs.CreateReport()<\/a> method. It accepts array of bytes instead of <code>.rdl<\/code> file name. This is relatively minor, since reading contents of a file is not that hard. Here&#8217;s the code:<\/p>\n<p><code><\/p>\n<pre>Dim len As Integer\nDim fileBytes As Byte()\nUsing stream As FileStream = File.OpenRead(path)\n    len = stream.Length\n    fileBytes = New [Byte](len - 1) {}\n    stream.Read(fileBytes, 0, len)\nEnd Using\n\nrs.CreateReport(\"MyReport\", \"Reports Folder\", overwrite, fileBytes, Nothing)<\/pre>\n<p><\/code><\/p>\n<p>It would be even easier if Microsoft did not mess up the VB example at the above link: they don&#8217;t read the last byte of the stream and the result is invalid XML. Interestingly, in the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa225813%28v=sql.80%29.aspx\">SQL 2000 example<\/a> they messed up the array initialization instead, so they send an extra byte to the SSRS server instead. The result is the server complaining about illegal 0x00 character in the end of the report.<\/p>\n<p>It seems difficult to comprehend, even for Microsoft people, that in VB.NET the number of elements in your array is different from the number you specify in <code>Dim<\/code>.<\/p>\n<p><b>Updating Data Source References<\/b><\/p>\n<p>Another hurdle is that report definitions, as stored by BIDS, contain invalid data source references. When you upload a report like outlined above, you will get a warning similar to this:<\/p>\n<p><code>The dataset `DataSet1' refers to the shared data source `MyDataSource', which is not published on the report server.<\/code><\/p>\n<p>HTTP traffic sniffing shows that when BIDS deploys a report, it gets the same warning. The solution is to update the data source references after the report has been uploaded, changing them to existing data sources in the <code>\"\/Data Sources\"<\/code> folder.<\/p>\n<p>This requires several steps. First, we need to load the report file as XML and locate all data source references.<\/p>\n<p><code><\/p>\n<pre>Dim doc As System.Xml.XmlDocument = New System.Xml.XmlDocument()\ndoc.Load(rdlPath)\n\nDim nsManager As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)\nnsManager.AddNamespace(\"r\", \"http:\/\/schemas.microsoft.com\/sqlserver\/reporting\/2008\/01\/reportdefinition\")\nDim nodes As XmlNodeList = doc.SelectNodes(\"\/r:Report\/r:DataSources\/r:DataSource\/r:DataSourceReference\", nsManager)<\/pre>\n<p><\/code><\/p>\n<p>Then we need to convert those nodes to <code>DataSource<\/code> objects recognized by SSRS:<\/p>\n<p><code><\/p>\n<pre>Dim dataSources As DataSource() = New DataSource(nodes.Count - 1) {}\n\nFor i As Integer = 0 To nodes.Count - 1\n    dataSources(i) = CreateDataSourceObj(nodes.Item(i))\nNext\n\nPrivate Function CreateDataSourceObj(ByVal refNode As XmlNode) As DataSource\n\n    Dim reference As DataSourceReference = New DataSourceReference\n    reference.Reference = \"\/Data Sources\/\" + refNode.InnerText\n\n    Dim result As DataSource = New DataSource\n    result.Name = CType(refNode.ParentNode, XmlElement).GetAttribute(\"Name\")\n    result.Item = reference\n\n    Return result\nEnd Function<\/pre>\n<p><\/code><\/p>\n<p>And finally, we need to call <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/reportservice2005.reportingservice2005.setitemdatasources.aspx\">rs.SetItemDataSources<\/a> method:<\/p>\n<p><code>rs.SetItemDataSources(serverReportPath, dataSources)<\/code><\/p>\n<p>Complete code for creating a report is <a href=\"http:\/\/www.ikriv.com\/dev\/misc\/ssrs\/DeployReport.vb\">here<\/a>.<br \/>\nCombined file for creating a data source and a report is <a href=\"http:\/\/www.ikriv.com\/dev\/misc\/ssrs\/Deploy.vb\">here<\/a>.<\/p>\n<p>It was fun, isn&#8217;t it? I am not sure why Microsoft did not make it simpler: SSRS reports are typically needed in an enterprise environment, and production deployment is an important part of development for the enterprise. It would also help if the code sample for <code>CreateReport<\/code>  were right: I spent quite some time trying to figure out why I am getting weird exceptions from SSRS before I noticed the size error.<\/p>\n<p>I hope this text will save others hours of boilerplate coding and frustration. <a style=\"display:none\" href=\"http:\/\/www.codeproject.com\/script\/Articles\/BlogFeedList.aspx?amid=1181663\" rel=\"tag\">CodeProject<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Deploying Reports Download code. In Part 2 we talked about deploying SSRS data sources. Now we are ready reports. Reports are deployed using rs.CreateReport() method. It accepts array of bytes <a href=\"https:\/\/ikriv.com\/blog\/?p=1261\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[14,16],"tags":[],"class_list":["entry","author-ikriv","post-1261","post","type-post","status-publish","format-standard","category-db","category-demos"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1261","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1261"}],"version-history":[{"count":0,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1261\/revisions"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}