Wednesday, May 21, 2008

SQL Server Reporting Service (SSRS) - HTTP Status 401 Unauthorized Error

I am going to continue on writing article on SQL Server Reporting Services (Its because, it is providing me good fame on http://forums.asp.net, LOL smile_wink).

We have to deploy the reports on the the Reporting Services Virtual Directory (I can write the whole different article on the Reporting Deployment, but may be next time. Right now we don't want to go deep into that.). The Reporting Server Virtual Directory may exist on the different server. It is recommended to keep anonymous access off for Reports virtual directory if you are going to call reports on the web.

The anonymous access allows any user to access the page. But now when we are keeping anonymous access off for the Reports, it can create problem while fetching the report inside the Report Viewer control on any ASPX page.

The Report server will expect authorized user to access the reports. This can be done by two ways.

  1. Passing the Report Server User Credentials with the Reports.
  2. Forms Authentication on Reporting Server.

Today, I am going to explain that How can we pass the User Credentials of the Reporting Server with the report call.

We need to Create one sealed class to perform this action. This class need to be inherited from IReportServerCredential interface.

    [Serializable]
public sealed class ReportServerNetworkCredentials : IReportServerCredentials
{
#region IReportServerCredentials Members

/// <summary>
/// Provides forms authentication to be used to connect to the report server.
/// </summary>
/// <param name="authCookie">A Report Server authentication cookie.</param>
/// <param name="userName">The name of the user.</param>
/// <param name="password">The password of the user.</param>
/// <param name="authority">The authority to use when authenticating the user, such as a Microsoft Windows domain.</param>
/// <returns></returns>
public bool GetFormsCredentials(out System.Net.Cookie authCookie, out string userName,
out string password, out string authority)
{
authCookie = null;
userName = null;
password = null;
authority = null;

return false;
}

/// <summary>
/// Specifies the user to impersonate when connecting to a report server.
/// </summary>
/// <value></value>
/// <returns>A WindowsIdentity object representing the user to impersonate.</returns>
public WindowsIdentity ImpersonationUser
{
get
{
return null;
}
}

/// <summary>
/// Returns network credentials to be used for authentication with the report server.
/// </summary>
/// <value></value>
/// <returns>A NetworkCredentials object.</returns>
public System.Net.ICredentials NetworkCredentials
{
get
{
string userName = "SERVERUSERNAME";
string domainName = "DOMAIN";
string password = "somepassword";

return new System.Net.NetworkCredential(userName, password, domainName);
}
}

#endregion
}



How to Utilize the ReportServerNetworkCredentials Class in your Report call on Page_Load event...



protected void Page_Load(object sender, EventArgs e)
{
myReportViewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Remote;

// Here we are going to pass the ReportServerCredentials to the Report Viewer.
myReportViewer.ServerReport.ReportServerCredentials = new ReportServerNetworkCredentials();

ReportServerLoaction = ConfigurationManager.AppSettings["REPORT_SERVER_PATH"];
myReportViewer.ServerReport.ReportServerUrl = new Uri("http://MyReportServer/Reports/");
myReportViewer.ServerReport.ReportPath = "TempReports/MyFirstReport";
myReportViewer.ShowParameterPrompts = false;
myReportViewer.ShowPrintButton = true;

Microsoft.Reporting.WebForms.ReportParameter[] reportParameterCollection = new Microsoft.Reporting.WebForms.ReportParameter[1];
reportParameterCollection[0] = new Microsoft.Reporting.WebForms.ReportParameter();
reportParameterCollection[0].Name = "ClientID";
reportParameterCollection[0].Values.Add("49020644-63AA-4D92-81A1-8F85D49ACF67");

myReportViewer.ServerReport.SetParameters(reportParameterCollection);
myReportViewer.ServerReport.Refresh();
}



Please feel free to comment on the article. Critics are highly appreciated.

12 comments:

Anonymous said...

After Implement the code,I getting an erro "The method or operation is not implemented." Can you help me solve this error

Nirav Patel said...

Hi,

Can you please give me detailed error message. That will help me to give you proper guidelines.

Regards,
Nirav Patel

Anonymous said...

how do you pass NULL parameter values?

Anonymous said...

nevermind, it was pretty straightforward. (null) did the trick :)

Anonymous said...

Thanks very much. Your class worked 100%.

Siya

Anonymous said...

Yes!, just what I'm after. The custom security extension approach only works SQL Server 2008 Enterprise Edition - this approach works with Express edition too. thanks.

Anonymous said...

hi
i hav created a report "Report1.rdl" but when i tried to deploy it on my report server at http://compname/ServerReport it is giving me error as....

A connection could not be made to the report server http://compname/ServerReport.
Additional Information:
Client found response content type of 'text/html; charset=utf=8', but expected 'text/xml' and so on.....

also i hav other problem with reporting services configuration manager that i am unable set web service identity & it is showing red cross...

Periyasamy said...

Thank you very much man. It really works for me. Continue your works

phani said...

where i have to write this code i.e. any new .cs file i have to create or i have to make any changes to existing cs file

Nirav Patel said...

Hi Phani,

You can write this code inside any cs file. It's just a class which you can add anywhere even in new CS or in existing cs file.

Please feel free to email me in case of more queries...

phani said...

Hi
Your code is working fine

Thank u

Keshav Sharma said...

thank you boss very much