title: SSRS Report Viewer + ASP.NET Credentials 401 Exception
body: <p>I have a report saved on a SQL2005 reporting server, and I want to return a rendered PDF of this report. I've figured this out when working with a local *.rdlc file (<a href="http://www.jarrettmeyer.com/2009/09/reports-in-aspnet-mvc.html" rel="noreferrer">and I've blogged about it</a>), but not when the *.rdl resides on a reporting server. I am getting a <strong>401 Not Authorized</strong> error at the line...</p>
  
  <pre><code>reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters);
  </code></pre>
  
  <p>Here's the method used to render the report.</p>
  
  <pre><code>public byte[] Render(IReportDefinition reportDefinition)
  {
      var reportViewer = new ReportViewer();
      byte[] renderedReport;
      try
      {
          var credentials = new WindowsImpersonationCredentials();
          reportViewer.ServerReport.ReportServerUrl = new Uri("http://myssrsbox", UrlKind.Absolute);
          reportViewer.ServerReport.ReportServerCredentials = credentials;
          reportViewer.ServerReport.ReportPath = reportDefinition.Path;
          // Exception is thrown on the following line...
          reportViewer.ServerReport.SetParameters(reportDefinition.ReportParameters);
  
          string mimeType;
          string encoding;
          string filenameExtension;
          string[] streams;
          Warning[] warnings;
  
          renderedReport = reportViewer.ServerReport.Render(reportDefinition.OutputType, reportDefinition.DeviceInfo, out mimeType, out encoding, out filenameExtension, out streams, out warnings);
      }
      catch (Exception ex)
      {
          // log the error...
          throw;
      }
      finally
      {
          reportViewer.Dispose();
      }
      return renderedReport;
  }
  </code></pre>
  
  <p>The other thing that you're missing is the WindowsImpersonationCredentials class.</p>
  
  <pre><code>public class WindowsImpersonationCredentials : IReportServerCredentials
  {
      public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority)
      {
          authCookie = null;
          userName = password = authority = null;
          return false;
      }
  
      public WindowsIdentity ImpersonationUser
      {
          get { return WindowsIdentity.GetCurrent(); }
      }
  
      public ICredentials NetworkCredentials
      {
          get { return null; }
      }
  
      public override string ToString()
      {
          return String.Format("WindowsIdentity: {0} ({1})", this.ImpersonationUser.Name, this.ImpersonationUser.User.Value);
      }
  }
  </code></pre>
  
  <p>Other things you may need to know... </p>
  
  <ul>
  <li>This is running on an intranet, and impersonation is turned on. </li>
  <li>Logging indicates that the impersonation user is being set correctly.</li>
  <li>This <strong>does work</strong> when running in Visual Studio (<code>http://localhost:devport</code>), and it <strong>does work</strong> when running on my development box (<code>http://localhost/myApplication</code>). It <strong>does not work</strong> when running on our test or production servers.</li>
  <li>I have tried solutions both with and without system.net.defaultProxy settings in web.config. Neither worked.</li>
  </ul>
  
  <p>What am I doing wrong? Is it a server setting? Is it code? Is it web.config?</p>