Credentials - Microsoft reporting library - c#

I have problem with Microsoft.Reporting library. I need to access SQL reporting services and I have report name, address of the server and username and password. First of all I need to get all parameters needed for one specific report.
Here is my implementation so far :
using System;
using System.Collections.Generic;
using Microsoft.Reporting.WinForms;
namespace ConsoleApp1
{
class Program
{
static IEnumerable<DataSourceCredentials> CredentialsEnumerable()
{
var credentials = new DataSourceCredentials
{
Name = #"domain\account",
Password = #"password"
};
yield return credentials;
}
static void Main(string[] args)
{
var credentials = new DataSourceCredentials
{
Name = #"domain\account",
Password = #"password"
};
var report = new ReportViewer
{
ProcessingMode = ProcessingMode.Remote
};
report.ServerReport.ReportPath = #"/Archiv/Daily sales";
report.ServerReport.ReportServerUrl = new Uri(#"http://serverIPaddress/reportserver");
report.ServerReport.SetDataSourceCredentials(credentials);
foreach (var param in report.ServerReport.GetParameters())
{
Console.WriteLine(param.ToString());
}
Console.ReadLine();
}
}
}
But I have problem with my code and mainly with :
report.ServerReport.SetDataSourceCredentials(credentials);
I am getting error, that it´s not possible to transfer from Microsoft.Reporting.WinForms.DataSourceCredentials to System.Collections.Generic.IEnumerable
I have already tryid to use variable "credentials" and created IEnumerable class but it´s not working.
Can you please suggest what is wrong with my code? How to fix it and provide credentials for reporting server? Without credentials I am getting error "Not authorized"
Thank you in advance

Problem solved - wrong credentials parameter.
Instead of :
report.ServerReport.SetDataSourceCredentials(credentials);
I used
report.ServerReport.ReportServerCredentials.NetworkCredentials = credentials;
And it´s working !

Related

USCG PSIX Web Service returning auth error

The United States Coast Guard runs a SOAP Web Service called PSIX:
https://cgmix.uscg.mil/xml/default.aspx
https://cgmix.uscg.mil/xml/PSIXData.asmx
https://cgmix.uscg.mil/xml/PSIXData.asmx?WSDL
Recently some software that has been accessing this web service for a ling time started erroring out, the error returned from PSIX is:
The HTTP request was forbidden with client authentication scheme 'Anonymous'.
There is a problem with the certificate on the site, but that's been like that for as long as we've been accessing the service (a little over a year and a half).
There is no mention on the USCG sites that I can find saying you need any kind of authentication to access the service - so I'm not sure what to do. There are also no contact details provided for the service I can find to ask if they've changed something on their side - there is comment form to which I've submitted a question about this issue.
The service was added into a .NET Core project using the Microsoft WCF Web Service Reference Provider. We create an instance if it with this static helper method.
Any ideas on how to get around the error?
private static PSIXDataSoap ServiceProxy
{
get {
try
{
if (_serviceProxy == null)
{
BasicHttpBinding binding = null;
binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); //Force use SSL, otherwise you get "expected http"
binding.MaxReceivedMessageSize = 20000000;
binding.MaxBufferSize = 20000000;
binding.MaxBufferPoolSize = 20000000;
binding.AllowCookies = true;
var factory = new ChannelFactory<PSIXDataSoap>(binding, new EndpointAddress("https://psix.uscg.mil/xml/PSIXData.asmx"));
//Tell it: Yes, I know the Coast Guard's Certificate is invalid...
factory.Credentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = X509RevocationMode.NoCheck
};
_serviceProxy = factory.CreateChannel();
}
return _serviceProxy;
}
catch (Exception)
{
return null;
}
}
}
And then access the proxy like:
var psixResponse = await ServiceProxy.getVesselSummaryAsync(vesselId_str, vesselName_str, callsign_str, vin_str, hin_str, flag_str, service_str, buildYear_str);
The following code work great. If it fails on your machine then it is probably a TLS issue. :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string URL = "https://cgmix.uscg.mil/xml/PSIXData.asmx?WSDL";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(URL);
}
}
}
Somewhere along the lines I guess the USCG changed the URL of their web service. So I:
Deleted and re-added the WCF Connected Service reference
Changed my service proxy helper method to use the new URL (I think this was the root cause of my problem).
As to why I needed to have the special helper method instead of creating the service reference from the built-in initializer, I think mainly because:
I needed to bypass the certificate error
I needed to increase the default message/buffer sizes because some of these calls can return a lot of information.
Anyway, new helper method that fixed my problem:
private static PSIXDataSoap ServiceProxy
{
get {
try
{
if (_serviceProxy == null)
{
BasicHttpBinding binding = null;
binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); //Force use SSL, otherwise you get "expected http"
binding.MaxReceivedMessageSize = 20000000;
binding.MaxBufferSize = 20000000;
binding.MaxBufferPoolSize = 20000000;
binding.AllowCookies = true;
//var factory = new ChannelFactory<PSIXDataSoap>(binding, new EndpointAddress("https://psix.uscg.mil/xml/PSIXData.asmx"));
var factory = new ChannelFactory<PSIXDataSoap>(binding, new EndpointAddress("https://cgmix.uscg.mil/xml/PSIXData.asmx")); //<--- NEW URL
//Tell it: Yes, I know the Coast Guard's Certificate is invalid...
factory.Credentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = X509RevocationMode.NoCheck
};
_serviceProxy = factory.CreateChannel();
}
return _serviceProxy;
}
catch (Exception)
{
return null;
}
}
}

creating a github issue in octokit.net

I am trying to write a script that will open an issue typed in the console.
For some reason the issue variable comes back empty in the debugger.
class Program
{
public async static Task Main()
{
var client = new GitHubClient(new ProductHeaderValue("test-app"));
var user = await client.User.Get("medic17");
var tokenAuth = new Credentials(APIKeys.GithubPersinalAccessToken);
client.Credentials = tokenAuth;
var exampleIssue = new NewIssue("test body");
var issue = await client.Issue.Create("owner","name", exampleIssue);
}
}
APIKeys holds my token.
Thanks
I found a solution hope this helps someone else as well.
class Program
{
public async static Task Main()
{
// client initialization and authentication
var client = new GitHubClient(new ProductHeaderValue("<anything>"));
var user = await client.User.Get("<user>");
var tokenAuth = new Credentials(APIKeys.GithubPersinalAccessToken);
client.Credentials = tokenAuth;
// user input
Console.WriteLine("Give a title for your issue: ");
string userIssueTitle = Console.ReadLine().Trim();
Console.WriteLine("Describe your issue:", Environment.NewLine);
string userIssue = Console.ReadLine().Trim();
// input validation
while (string.IsNullOrEmpty(userIssue) || string.IsNullOrEmpty(userIssueTitle))
{
Console.WriteLine("ERROR: Both fields must contain text");
Console.ReadLine();
break;
}
var newIssue = new NewIssue(userIssueTitle) { Body = userIssue };
var issue = await client.Issue.Create(<owner>, <repo> newIssue);
var issueId = issue.Id;
Console.WriteLine($"SUCCESS: your issue id is {issueId} ");
Console.ReadLine();
}
}
Note
You need to store your keys in a separate file and write a class for it so your authentication flow might be different.
Note 2
You must replace all text with real values.
Still a little confused the app is OpenSource for transport since it deals with HIPPA data, users who want to use it need GitHub account if they want to do any error reporting. I assume I don’t share the authToken in the source of the project but the desktop Binary needs it plus the users GitHub login and password. Any pointers? I have tried just using username password that gets entered when creating issue but that fails with “not found”. It seems like any secret that gets deployed with binary app is potentially an issue.

Authenticating Website Members as Users in CKFinder v3

Before beginning this question, I should point out that my knowledge of ASP.NET & C# is pretty much nil.
I'm in the process of trying to integrate the ASP.NET version of CKFinder v3 into a site built in a different language and all is going well so far; I have everything setup as I want it and it's working when I grant unrestricted access to CKF but I'm stuck at the point now of trying to restrict access to it by authenticating only certain members of my site to use it. All the pages that CKFinder appears on on my site are only accessible by those certain members but I need an extra level of security if, for example, anyone figures out the direct path to my "ckfinder.html" file.
In the ASP version of CKFinder, I simply added this line in the function that checks my member's privileges, where isEditor was a boolean whose value was assigned per member based on information from my database:
session("accessckf")=isEditor
and then edited the CheckAuthentication() function in CKFinder's "config.asp" file to read:
function CheckAuthentication()
CheckAuthentication=session("accessckf")
end function
Reading through this "Howto", authentication seems to be much more complex in v3 but, after a lot of trial and error and some help from Lesiman, I created this C# file, which is located in my CKF directory:
<%#page codepage="65001" debug="true" language="c#" lcid="6153"%>
<%#import namespace="CKSource.CKFinder.Connector.Core"%>
<%#import namespace="CKSource.CKFinder.Connector.Core.Authentication"%>
<%#import namespace="CKSource.CKFinder.Connector.Core.Builders"%>
<%#import namespace="CKSource.CKFinder.Connector.Host.Owin"%>
<%#import namespace="Owin"%>
<%#import namespace="System.Data.Odbc"%>
<%#import namespace="System.Threading"%>
<%#import namespace="System.Threading.Tasks"%>
<script runat="server">
public void Configuration(IAppBuilder appBuilder){
var connectorBuilder=ConfigureConnector();
var connector=connectorBuilder.Build(new OwinConnectorFactory());
appBuilder.Map("/path/to/connector",builder=>builder.UseConnector(connector));
}
public ConnectorBuilder ConfigureConnector(){
var connectorBuilder=new ConnectorBuilder();
connectorBuilder.SetAuthenticator(new MyAuthenticator());
return connectorBuilder;
}
public class MyAuthenticator:IAuthenticator{
public Task<IUser> AuthenticateAsync(ICommandRequest commandRequest,CancellationToken cancellationToken){
var domain=HttpContext.Current.Request.Url.Host;
var cookie=HttpContext.Current.Request.Cookies[urlDomain];
var password="";
var username="";
var user=new User(false,null);
if (cookie!=null){
if (cookie["username"]!=null)
username=cookie["username"];
if (cookie["password"]!=null)
password=cookie["password"];
if(username!=""&&password!=""){
var connection=new OdbcConnection("database=[database];driver=MySQL;pwd=[pwd];server=[server];uid=[uid];");
connection.Open();
OdbcDataReader records=new OdbcCommand("SELECT ISEDITOR FROM MEMBERS WHERE USERNAME='"+username+"' AND PASSWORD='"+password+"'",connection).ExecuteReader();
if(records.HasRows){
records.Read();
bool isEditor=records.GetString(0)=="1";
var roles="member";
if(isEditor)
roles="editor,member";
user=new User(isEditor,roles.Split(','));
}
records.Close();
connection.Close();
}
}
return Task.FromResult((IUser)user);
}
}
</script>
Loading that page produces no errors (which doesn't necessarily mean it's working as trying to write anything to screen from within the public class doesn't work, for some reason) so now I'm at the stage of somehow checking that file for authentication.
Originally, I had tried loading it via XMLHttp from within my function that checks membership privileges for the site but, as I suspected and as Lesmian confirmed, that wouldn't work. After more trial & error, I added code to check website member privileges to the C# file, which leads me to where I am now: stuck!
What do I need to edit within CKFinder in order to have it use this custom file to check whether or not a user is authenticated?
First you'll need a connector between the ASP's Session and CKFinder's .Net authenticator. Here's an example that serializes ASP Session contents into JSON.
Put the connector.asp into a publicly accessible location. http://myaspwebsite.com/connector.asp for example.
connector.asp
<%#Language=VBScript CodePage=65001%>
<% Option Explicit %>
<!--#include file="JSON.asp"-->
<%
' obtain JSON.asp from https://github.com/tugrul/aspjson/archive/master.zip
' just for testing, must be removed in the production environment
Session("isEditor") = True
Session("isMember") = True
' only local requests allowed
' instead of local and remote ip comparison, a secret key can be used
If Request.ServerVariables("LOCAL_ADDR") <> Request.ServerVariables("REMOTE_ADDR") Then
Response.Status = "403 Forbidden"
Response.End
End If
Response.ContentType = "application/json"
Response.Charset = "utf-8"
Dim JSONObject, Key
Set JSONObject = jsObject()
For Each Key In Session.Contents
If Not IsObject(Session.Contents(Key)) Then 'skip the objects cannot be serialized
JSONObject(Key) = Session.Contents(Key)
End If
Next
JSONObject.Flush
%>
CKFinder 3.3.0 comes with a default connector which can be found in /ckfinder/bin/CKSource.CKFinder.Connector.WebApp.dll, remove it.
Examine the following program and remember to replace builder.Map("/connector", SetupConnector); and new Uri("http://myaspwebsite.com/connector.asp"); with your own values.
It simply authenticates the users by checking ASP Session varaibles isEditor and isMember via connector.asp and finally claims the roles editor , member or none.
I assume that you have configured the roles editor and member in the web.config.
Then put the Shaggy.cs into /ckfinder/App_Code. Create App_Code directory if not exist. .Net files in this folder will be compiled on the fly.
For more information have a look at Shared Code Folders in ASP.NET Web Projects
Shaggy.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Newtonsoft.Json.Linq;
using Owin;
[assembly: Microsoft.Owin.OwinStartup(typeof(CKSource.CKFinder.Connector.Shaggy.Startup))]
namespace CKSource.CKFinder.Connector.Shaggy
{
using FileSystem.Local;
using FileSystem.Dropbox;
using Core;
using Core.Authentication;
using Config;
using Core.Builders;
using Core.Logs;
using Host.Owin;
using Logs.NLog;
using KeyValue.EntityFramework;
public class Startup
{
public void Configuration(IAppBuilder builder)
{
LoggerManager.LoggerAdapterFactory = new NLogLoggerAdapterFactory();
RegisterFileSystems();
builder.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
AuthenticationMode = AuthenticationMode.Active
});
//replace connector path with yours
builder.Map("/connector", SetupConnector);
}
private static void RegisterFileSystems()
{
FileSystemFactory.RegisterFileSystem<LocalStorage>();
FileSystemFactory.RegisterFileSystem<DropboxStorage>();
}
private static void SetupConnector(IAppBuilder builder)
{
var keyValueStoreProvider = new EntityFrameworkKeyValueStoreProvider("CacheConnectionString");
var authenticator = new ShaggysAuthenticator();
var connectorFactory = new OwinConnectorFactory();
var connectorBuilder = new ConnectorBuilder();
var connector = connectorBuilder
.LoadConfig()
.SetAuthenticator(authenticator)
.SetRequestConfiguration(
(request, config) =>
{
config.LoadConfig();
config.SetKeyValueStoreProvider(keyValueStoreProvider);
})
.Build(connectorFactory);
builder.UseConnector(connector);
}
}
public class ShaggysAuthenticator : IAuthenticator
{
// this method makes an http request on the background to gather ASP's all session contents and returns a JSON object
// if the request contains ASP's session cookie(s)
private static JObject GetAspSessionState(ICommandRequest requestContext)
{
// building Cookie header with ASP's session cookies
var aspSessionCookies = string.Join(";",
requestContext.Cookies.Where(cookie => cookie.Key.StartsWith("ASPSESSIONID"))
.Select(cookie => string.Join("=", cookie.Key, cookie.Value)));
if (aspSessionCookies.Length == 0)
{
// logs can be found in /ckfinder/App_Data/logs
LoggerManager.GetLoggerForCurrentClass().Info("No ASP session cookie found");
// don't make an extra request to the connector.asp, there's no session initiated
return new JObject();
}
//replace this URL with your connector.asp's
var publicAspSessionConnectorUrl = new Uri("http://myaspwebsite.com/connector.asp");
var localSafeAspSessionConnectorUrl = new UriBuilder(publicAspSessionConnectorUrl) { Host = requestContext.LocalIpAddress };
using (var wCli = new WebClient())
try
{
wCli.Headers.Add(HttpRequestHeader.Cookie, aspSessionCookies);
wCli.Headers.Add(HttpRequestHeader.Host, publicAspSessionConnectorUrl.Host);
return JObject.Parse(wCli.DownloadString(localSafeAspSessionConnectorUrl.Uri));
}
catch (Exception ex) // returning an empty JObject object in any fault
{
// logs can be found in /ckfinder/App_Data/logs
LoggerManager.GetLoggerForCurrentClass().Error(ex);
return new JObject();
}
}
public Task<IUser> AuthenticateAsync(ICommandRequest commandRequest, CancellationToken cancellationToken)
{
var aspSessionState = GetAspSessionState(commandRequest);
var roles = new List<string>();
var isEditor = aspSessionState.GetNullSafeValue("isEditor", false);
var isMember = aspSessionState.GetNullSafeValue("isMember", false);
if (isEditor) roles.Add("editor");
if (isMember) roles.Add("member");
var isAuthenticated = isEditor || isMember;
var user = new User(isAuthenticated, roles);
return Task.FromResult((IUser)user);
}
}
public static class JObjectExtensions
{
// an extension method to help case insensitive lookups with a default value to get avoid NullReferenceException
public static T GetNullSafeValue<T>(this JObject jobj, string key, T defaultValue = default(T))
{
dynamic val = jobj.GetValue(key, StringComparison.OrdinalIgnoreCase);
if (val == null) return defaultValue;
return (T)val;
}
}
}
Now you should have a working CKFinder connector. Change the logic in the method AuthenticateAsync if you need and see how CKFinder handles your Classic ASP membership management.
Did you setup your custom authentication provider with ConnectorBuilder?
public ConnectorBuilder ConfigureConnector()
{
var connectorBuilder = new ConnectorBuilder();
connectorBuilder.SetAuthenticator(new MyAuthenticator());
return connectorBuilder;
}
You can find full example here: http://docs.cksource.com/ckfinder3-net/configuration_by_code.html.
UPDATE
Additionally you should register ConnectorBuilder inside Startup class to add it to request pipeline:
public void Configuration(IAppBuilder appBuilder)
{
var connectorBuilder = ConfigureConnector();
var connector = connectorBuilder.Build(new OwinConnectorFactory());
appBuilder.Map("/CKFinder/connector", builder => builder.UseConnector(connector));
}
All this is from a documentation link I've provided before.

Programmatically setting the 'Connect as' user in IIS7 using C#

I'm attempting to do this using the following code snippet, but the FindElement keeps giving me errors indicating it doesn't exist in the current context. Ultimately what I'm trying to do is set the username and password the website uses in the connect as area. This is different from the impersonation user.
using Microsoft.Web.Administration;
using Microsoft.Web.Management;
using Microsoft.Web.Media.TransformManager.Common;
using Microsoft.Web.Media.TransformManager;
using System.Web.Configuration;
using System.Collections;
Configuration config = iisManager.GetApplicationHostConfiguration();
ConfigurationSection sitesSection = config.GetSection("system.applicationHost/sites");
ConfigurationElementCollection sitesCollection = sitesSection.GetCollection();
ConfigurationElement siteElement = FindElement(sitesCollection, "site", "name", #"Default Web Site");
ConfigurationElementCollection applicationCollection = siteElement.GetCollection();
ConfigurationElement applicationElement = FindElement(applicationCollection, "application", "path", #"/MyNewVirtualDir");
ConfigurationElementCollection virtualDirCollection = applicationElement.GetCollection();
ConfigurationElement virtualDirElement = FindElement(virtualDirCollection, "virtualDirectory", "path", #"/");
virtualDirElement.Attributes["userName"].Value = "MYDOMAIN\\MyUser";
virtualDirElement.Attributes["password"].Value = "MyPassword";
EDIT : So as I was staring at the question after beating my head against this for a few days, I discovered you can accomplish this using ServerManager in the following context.
ServerManager iisManager = new ServerManager()
site = iisManager.Sites.FirstOrDefault(a => a.Name.Contains("Default"));
site.VirtualDirectoryDefaults.Password = tbImpersonatorPassword.Text;
site.VirtualDirectoryDefaults.UserName = tbImpersonatorUser.Text;
So as I was staring at the question after beating my head against this for a few days, and apparently you can accomplish this using Servermanager in the following context.
ServerManager iisManager = new ServerManager()
site = iisManager.Sites.FirstOrDefault(a => a.Name.Contains("Default"));
site.VirtualDirectoryDefaults.Password = tbImpersonatorPassword.Text;
site.VirtualDirectoryDefaults.UserName = tbImpersonatorUser.Text;
Setting the Username and Password on the VirtualDirectoryDefaults may not yield the results you are looking for. Instead you may want to locate the app within this Site object whose path is the root (hence the .Path.Equals("/") filter on the query), then modify that apps Virtual Directory username and password.
This can be accomplished with the following method (Please Note: this method assumes that you have already located the desired Site via a search on the ServerManagers Sites collection and that you are passing that Site object into this method). Be sure to dispose of the ServerManager object when you are done in order to avoid a memory leak.
public static void SetConnectAsAccount(Site site, string username, string password)
{
if (site == null)
{
throw new ArgumentNullException("site");
}
if (string.IsNullOrWhiteSpace(username))
{
throw new ArgumentNullException("username");
}
if (string.IsNullOrWhiteSpace(password))
{
throw new ArgumentNullException("password");
}
foreach (var app in site.Applications.Where(c => c.Path.Equals("/")))
{
try
{
// set the Connect-As Accounts login credentials to the Service Acount
var appVirDir = app.VirtualDirectories.Where(c => c.Path.Equals("/")).FirstOrDefault();
if (appVirDir != null)
{
appVirDir.UserName = username;
appVirDir.Password = password;
}
}
catch (Exception ex)
{
// log your exception somewhere so you know what went wrong
}
}
}

Update Data Source and DataSet reference for SSRS 2012 Deployment from C#

EDIT: I think I can simplify this question a bit to ask for only what is needed to know:
I am working with C# using the SSRS 2010 Web Service:
'ReportService2010.asmx' http://technet.microsoft.com/en-us/library/ee640743.aspx
I can use the method 'CreateDataSource' to create a Datasource on an instance of an SSRS Server http:// (servername)/ReportServer.
I can also use the method 'CreateCatalogItem' to create a report on a server from referencing a project's RDL local file to serialize it to a byte array and then pass that as a 'Definition' to the method to create it on the server.
Now everything I do works with a caveat, and a major one. I can only deploy everything to the same folder. If I deploy a Data Source to say the 'Data Sources' folder and then a report to say: 'Test Reports', the report does not know it has a shared data source to reference at a different location. So I dug a little at the technet articles and have tried to 'GetItemDataSources' method but it only gives a name and a type for the ReportingService2010.DataSource return type. Does anyone know the method to link up a 'Report' or 'Dataset's CatalogItem property of 'DataSource', so it points to a reference in a different folder on the SSRS Server when deploying? There has to be a way to do it as I know I can deploy from Business Intelligence Development Studio and it can do this.
I've had similar issues when deploying report files; when deploying through rs.exe or code you run into these issues where reports lose their link to a Data Source.
We solved this by explicitly pointing the report to the server-side Data Source immediately after being deployed by our application; is this similar to what you're trying to do?
Anyway, here's the slightly adapted code we use in our report deployment application:
static void SetReportDataSource(string reportPath)
{
string dsPath = CombinePath(DataSourcePath, DataSourceFolder, DataSourceName);
DataSourceReference dsRef = new DataSourceReference()
{
Reference = dsPath
};
DataSource ds = new DataSource();
ds.Item = dsRef as DataSourceDefinitionOrReference;
ds.Name = DataSourceName;
var rptDataSources = Server.GetItemDataSources(reportPath);
foreach (var rptDs in rptDataSources)
{
Server.SetItemDataSources(filePath, new DataSource[] { ds });
}
}
So, basically we have variables that define information like the Data Source name, Data Source location on server, and the same for a report. They can be in different folders.
Based on this, we create a new reference to a Data Source and then repoint the report to this using SetItemDataSources.
This sorted out the Data Source issue for me, anyway. Not sure about Shared Datasets and how they handle all of this, but hopefully this will be of some help.
Also, just thought that this would be using the ReportService2005 endpoint, but it's probably not too different for ReportService2010.
Edit:
For the paths mentioned here, these are relative to the server, e.g. /Reports/. You don't need the fully qualified name as you define the Url property of the ReportService2010 object which contains the destination.
Maybe this might be some help. I used it to reset the DataSource for all the reports in a given Parent Folder, and it's subfolders:
using System;
using GetPropertiesSample.ReportService2010;
using System.Diagnostics;
using System.Collections.Generic; //<== required for LISTS
using System.Reflection;
namespace GetPropertiesSample
{
class Program
{
static void Main(string[] args)
{
GetListOfObjectsInGivenFolder_and_ResetTheReportDataSource("0_Contacts"); //<=== This is the parent folder
}
private static void GetListOfObjectsInGivenFolder_and_ResetTheReportDataSource(string sParentFolder)
{
// Create a Web service proxy object and set credentials
ReportingService2010 rs = new ReportingService2010();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
CatalogItem[] reportList = rs.ListChildren(#"/" + sParentFolder, true);
int iCounter = 0;
foreach (CatalogItem item in reportList)
{
iCounter += 1;
Debug.Print(iCounter.ToString() + "]#########################################");
if (item.TypeName == "Report")
{
Debug.Print("Report: " + item.Name);
ResetTheDataSource_for_a_Report(item.Path, "/DataSources/Shared_New"); //<=== This is the DataSource that I want them to use
}
}
}
private static void ResetTheDataSource_for_a_Report(string sPathAndFileNameOfTheReport, string sPathAndFileNameForDataSource)
{
//from: http://stackoverflow.com/questions/13144604/ssrs-reportingservice2010-change-embedded-datasource-to-shared-datasource
ReportingService2010 rs = new ReportingService2010();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
string reportPathAndName = sPathAndFileNameOfTheReport;
//example of sPathAndFileNameOfTheReport "/0_Contacts/207_Practices_County_CareManager_Role_ContactInfo";
List<ReportService2010.ItemReference> itemRefs = new List<ReportService2010.ItemReference>();
ReportService2010.DataSource[] itemDataSources = rs.GetItemDataSources(reportPathAndName);
foreach (ReportService2010.DataSource itemDataSource in itemDataSources)
{
ReportService2010.ItemReference itemRef = new ReportService2010.ItemReference();
itemRef.Name = itemDataSource.Name;
//example of DataSource i.e. 'itemRef.Reference': "/DataSources/SharedDataSource_DB2_CRM";
itemRef.Reference = sPathAndFileNameForDataSource;
itemRefs.Add(itemRef);
}
rs.SetItemReferences(reportPathAndName, itemRefs.ToArray());
}
}
}

Categories