Crezzer7
Crezzer7

Reputation: 2335

Download SSRS Report and save in specific location (C#) (Unauthorized)

Question

I am attempting to download an SSRS report via its URL into a data buffer (byte array), so therefore I can then save it in a particular folder, with a name of my choosing. I am open to suggestions of different ways of doing this if required.

The Issue

However I am constantly getting the below error (401) Unauthorized, no matter which credentials I enter:

An exception of type 'System.Net.WebException' occurred in System.dll but was not handled in user code

Additional information: The remote server returned an error: (401) Unauthorized.

I am using this code (C#):

WebClient myWebClient = new WebClient();
NetworkCredential netCredential = new NetworkCredential("username", "password");
myWebClient.Credentials = netCredential;

var theURL = "http://ReportServer/ReportServer_MYSERVER/Pages/ReportViewer.aspx?%2fPurchaseOrder&rs:Command=Render&OrderID=100&rs:ClearSession=true&rs:Format=PDF"

byte[] myDataBuffer = myWebClient.DownloadData(theURL);

example URL (this downloads the file perfectly if I simply copy the below URL into my browser, no issues with the access whatsoever): http://ReportServer/ReportServer_MYSERVER/Pages/ReportViewer.aspx?%2fPurchaseOrder&rs:Command=Render&OrderID=100&rs:ClearSession=true&rs:Format=PDF

My machine is on a domain, and I have tried these credentials, along with the domain, and also the database SA account, but both deliver the same issue.

I know this code works when downloading a PDF file, as I hard-coded a random URL from the internet and this worked, for example: "http://www.axmag.com/download/pdfurl-guide.pdf"

Thankyou all for help on this matter, im hoping that this is possible as this would be a very handy addition to my application

Upvotes: 6

Views: 26055

Answers (4)

Michael Gendy
Michael Gendy

Reputation: 21

I wrote in vb.net using custom authentication as following,

     
private sub GenerateReportPDF () 
 Dim username As String = "username"
          Dim password As String = "password"
          Dim strURL As String = $"https://server/ReportServer/Pages/ReportViewer.aspx?Report&param1=" + Param1 + "&Param2=" + Param1 + "&rs:Format=PDF"

          'prepare the request'
          Dim req As WebClient = New WebClient()
          req.Credentials = CredentialCache.DefaultCredentials
          req.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials
          req.UseDefaultCredentials = True

          Dim myCache As New CredentialCache()
          myCache.Add(New Uri($"https://server/reportserver"), "NTLM", New System.Net.NetworkCredential(username, password, "domainName"))
          req.Credentials = myCache

          'prepare the response'
          Dim myResponse As HttpResponse = HttpContext.Current.Response
          myResponse.Clear()
          myResponse.ClearContent()
          myResponse.ClearHeaders()
          myResponse.Buffer = True
          myResponse.ContentType = "application/pdf"
          myResponse.BinaryWrite(req.DownloadData(strURL))
          myResponse.End()
End Sub

Upvotes: 2

tmndungu
tmndungu

Reputation: 358

Worked for me, only difference used HTTPClient

var theURL = "http://ReportServer/ReportServer_MYSERVER/Pages/ReportViewer.aspx?%2fPurchaseOrder&rs:Command=Render&OrderID=100&rs:ClearSession=true&rs:Format=PDF";

var httpClientHandler = new HttpClientHandler()
                                    {
                                        UseDefaultCredentials = true
                                    };

            HttpClient webClient = new HttpClient(httpClientHandler);

            byte[] response = await webClient.GetByteArrayAsync(theURL);

Upvotes: 0

Kaarthikeyan
Kaarthikeyan

Reputation: 570

Using the ReportExecutionService class will be a best alternative solution. The chance of report getting failed to download is very less.

Every Microsoft SQL Server Reporting Server provide an SOAP End-point to ReportExecutionService. Third party application can use this extension to get connected to reporting server.

For .Net applications, using Visual Studio we can add Web Reference to the SOAP end-point http://(your_server_url)/reportserver/reportexecution2005.asmx (ReportExecutionService).

This will generate the necessary namepsaces and classed to the SOAP End-Point, which we can consume in our application to download the reports.

A Sample code is given below. The steps to add Web Reference, common errors and other details on this method can be found at

https://www.craftedforeveryone.com/download-sql-server-reporting-service-ssrs-report-as-pdf-using-c-sharp/

Note: We do not have NuGet Package or library available to resolve the namespace ReportExecutionService. Adding Web Reference to your Reporting server will resolve this.

using DownloadSSRSReport.craftedforeveryone.com;
using System.Collections.Generic;
using System.IO;
using System.Net;

namespace DownloadSSRSReport
{
class Program
{
static void Main(string[] args)
{
ReportExecutionService rs = new ReportExecutionService();
rs.Credentials = CredentialCache.DefaultCredentials;
rs.Url = "http://craftedforeveryone.com/reportserver/reportexecution2005.asmx";

rs.ExecutionHeaderValue = new ExecutionHeader();
var executionInfo = new ExecutionInfo();
executionInfo = rs.LoadReport("/your report path/report name", null);

List<ParameterValue> parameters = new List<ParameterValue>();

parameters.Add(new ParameterValue { Name = "parameterId", Value = "value" });

rs.SetExecutionParameters(parameters.ToArray(), "en-US");


string deviceInfo = "<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
string mimeType;
string encoding;
string[] streamId;
Warning[] warning;

var result = rs.Render("PDF", deviceInfo, out mimeType, out encoding, out encoding, out warning, out streamId);
File.WriteAllBytes("c:\\temp\\report.pdf", result);

}
}
}

Upvotes: 1

Crezzer7
Crezzer7

Reputation: 2335

it turns out it was as simple as this for my scenario (using Default Credentials):

var theURL = "http://ReportServer/ReportServer_MYSERVER/Pages/ReportViewer.aspx?%2fPurchaseOrder&rs:Command=Render&OrderID=100&rs:ClearSession=true&rs:Format=PDF";

WebClient Client = new WebClient();
Client.UseDefaultCredentials = true;

byte[] myDataBuffer = Client.DownloadData(theURL);

this code above enables any SSRS report to be downloaded as a byte array. This then means that it can be saved in a specified location, with a name of your choice:

var filename = "Test.PDF";
var fileStructureLocal = "C:\\Test";
var fileStructureNetwork = "\\\\NetworkDrive\TestFolder";

var fileLocation = fileStructureNetwork + "\\" + filename;

 if (System.IO.File.Exists(url) == true)
        {
            //DO NOTHING
        }
 else
        {
            System.IO.File.WriteAllBytes(url, myDataBuffer);
            //SAVE FILE HERE
        }

this next block is how you rename the file, and specify the location. I have also added a check to see if it already exists, if it does it simply does nothing.

I hope this helps as this is something I have been trying to get working for a long time!

Upvotes: 12

Related Questions