Wednesday, March 7, 2012

ReportingService2005.CreateReport() warning...

I am using Reporting Services 2005 on SQL Express with Advanced Services...

I am dipping into the SOAP API and trying to add DataSources and Reports dynamically, as is how I would like to be able to deploy them...

My problem is this:

I have a shared datasource and a report that were deployed to the server via the 'Deploy' method in VSTS...I can access that report just fine, and it obviously uses the shared datasource...

Next, I copy the .rdl file of the report I already deployed and give it another name ("NewReport.rdl"). What I want to do is add this report to the server (it's an exact copy of the functioning report with a different report name). This report should use the same shared datasource as the other report.

Here is my code:

ReportingService2005 rs = new ReportingService2005();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;

Byte [] reportDefinition = /* read in the rdl file and create byte array out of it (didn't want to paste this code, cuz you don't care...trust me, it's correct */

ReportingTest.localhost.Warning [] warnings = rs.CreateReport("NewReport", "/ReportServerTest", true, reportDefinition, null);

foreach (ReportingTest.localhost.Warning warning in warnings)
{
Console.WriteLine(warning.Message);
}


The report is added to the server just fine, but I receive this 1 warning:

Code: "rsDataSourceReferenceNotPublished"
Message: "The data set ‘AdventureWorksTestDataSource’ refers to the shared data source ‘AdventureWorksTestDataSource’, which is not published on the report server."

And then when I try to view the report, I get this exception:

"The report server cannot process the report. The data source connection information has been deleted. (rsInvalidDataSourceReference)"

I know that the datasource is there, because the other report still works just fine...and I am adding an exact COPY of that report's RDL to the server, so it SHOULD work, IMO...

Any word on this?...I haven't been able to find much on this error...they say that an 'rsInvalidDataSourceReference' is usually caused when the datasource doesn't exist on the server when the report is deployed...or the datasource is deleted after the report has been deployed, but this is not true in my case...

Thanks for any feedback!!

Russ

Are you publishing it ot the same location? Check to see if the original report is using an absolute or relative path to the data source. If it is a relative path, then you will need to adjust it in your copy if you are publishing it to a different location.|||

I am publishing it to the same folder on the same server...the reports are right next to each other...

Here is the 'DataSources' excerpt of the XML...

<DataSources>
<DataSource Name="AdventureWorksTestDataSource">
<DataSourceReference>AdventureWorksTestDataSource</DataSourceReference>
<rd:DataSourceID>ea3ad893-2132-478e-94fb-9fdff9803ed5</rd:DataSourceID>
</DataSource>
</DataSources>

I can do a GetReportDefinition on the ReportingService2005 object and get the original report, and it will return the exact RDL file that I'm using to upload...

Any other ideas?

Thanks for the help...

|||Has anyone else received this type of error?|||Where is the datasource in relation to the reports? Is it in the same folder?|||


No, they aren't...

Here is the File Structure...

Root
|
|
|
|DataSources
| |
| |AdventureWorksTestDataSource
|
|ReportServerTest
|
|AdvenctureWorksTestReport
|
|NewReport

Again, I'm using the same RDL structure and data that is coming from the report that IS working...i'm just re-creating that same report with a different name...that's why I'm not sure if it's a directories problem...I think ALL Datasources are assumed to be in the DataSources directory(or a subdirectory of that directory), aren't they?

You may have noticed that the First Report is spelled incorrectly, but that doesn't matter...so, don't let that scream at you as a gotcha...

Thanks for your help!

Russ

|||

I assume you published this report with the designer, am I correct?

The designer publishes reports in two passes. First it publishes the report definition via CreateReport(), and then it calls SetItemDataSources() to bind the data sources. This second call to SetItemDataSources() sets the location and logon options for the data source. Essentially it "fixes up" the data source references to point to the location that the designer will actually put them. There is not really anything special about the "Data Sources" folder... It is just the default location where the designer will put data sources.

Unfortunately, the new location of the data source is not reflected in the RDL that comes out of GetReportDefinition() because by design this returns exactly the RDL that was published.

If you want to emulate the behavior of the designer in order to perform a copy, then you will have to first call CreateReport() to publish the report, find the data sources (use GetItemDataSources()), and then resolve the data sources by calling SetItemDataSources() on the new copy of the report.

|||

That suggestion helped!!!...Here is the code that allows me to do it, if anyone else runs into this problem! Thanks again!

ReportingService2005 rs = new ReportingService2005();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
CatalogItem[] catalogItems = rs.ListChildren("/", true);
DataSourceDefinition dsDefinition = new DataSourceDefinition();
dsDefinition.CredentialRetrieval = CredentialRetrievalEnum.Store;
dsDefinition.ConnectString = @."Data Source=.\SQLExpress;Initial Catalog=AdventureWorks";
dsDefinition.Enabled = true;
dsDefinition.OriginalConnectStringExpressionBased = false;
dsDefinition.WindowsCredentials = false;
dsDefinition.ImpersonateUser = false;
dsDefinition.Extension = "SQL";
dsDefinition.Prompt = null;
dsDefinition.UserName = "username";
dsDefinition.Password = "p@.ssword";
Byte[] reportDefinition = null;

try
{
System.IO.FileStream stream = System.IO.File.OpenRead("DynamicTestReport.rdl");
reportDefinition = new Byte[stream.Length];
stream.Read(reportDefinition, 0, (int)stream.Length);
stream.Close();
}
catch (System.IO.IOException ioe)
{
Console.WriteLine(ioe.Message);
}
try
{
rs.CreateDataSource("DynamicDataSource", "/Data Sources", true, dsDefinition, null);
ReportingTest.localhost.Warning [] warnings = rs.CreateReport("DynamicTestReport", "/ReportServerTest", true, reportDefinition, null);
DataSource[] dataSources = rs.GetItemDataSources("/ReportServerTest/DynamicTestReport");

foreach (DataSource ds in dataSources)
{
if (ds.Item.GetType() == typeof(ReportingTest.localhost.InvalidDataSourceReference))
{
DataSource newDS = new DataSource();
DataSourceReference dsRef = new DataSourceReference();
dsRef.Reference = "/Data Sources/DynamicDataSource";
newDS.Item = dsRef;
newDS.Name = "DynamicDataSource";
DataSource[] newDataSources = new DataSource[]{newDS};
rs.SetItemDataSources("/ReportServerTest/DynamicTestReport", newDataSources);
}

}
}
catch (SoapException ex)
{
Console.WriteLine(ex.Message);
}

|||

Thanks for sharing.

I've got one question.

In "ReportingTest.localhost.Warning[]...", I am not sure from what class is the object ReportingTest created?

Many thanks in advance for your reply.

John

No comments:

Post a Comment