Lars Nielsen's Discoveries

July 13, 2012

SharePoint Designer, Reporting Services and UAG

Filed under: Development,SharePoint,Troubleshooting — Lars Nielsen @ 6:51 pm
Tags: , ,

I set up a SharePoint 2010 environment with Forefront UAG and Kerberos authentication throughout, all via SSL.  Now our SharePoint sites can be published out to the Internet with a protection barrier.  It all works fine for general browsing and opening documents.  And now finally I  have solved the problem of people having to authenticate again when opening documents from SharePoint…  With UAG they authenticate once when they browse to the site and then that’s it.  They can click to open documents from SharePoint, edit documents,  and even open the document library in Explorer view without having to authenticate again.

So having got all that working, I thought: let’s push the envelope a bit and see what happens when we try to use Reporting Services reports in SharePoint Integrated mode over UAG.   Not only that, but the SSRS reports we were trying to deploy into SharePoint included hard links on the report which reference the Report Server URL directly using the ReportServerURL built-in field in the link.  So for example with regular Reporting Services your report server URL might be http://MyServer/ReportServer and then dynamicallythe report creates a link like this:

http://MyServer/ReportServer?https://myportal.domain.com/Reports/Myreport.rdl&rs:Command=Render&MyParameter=Something

That’s fine when the browser can get to http://MyServer but of course once you’re out on the Internet that URL won’t work because there’s no public DNS entry for it.  So the link will break.  You can work round this because SharePoint creates a proxy address for the Report Server which you can use instead.  The URL is like this:

https://myportal.domain.com/_vti_bin/ReportServer

OK so then this should work as the link to the report:

https://myportal.domain.com/_vti_bin/ReportServer?https://myportal.domain.com/Reports/Myreport.rdl&rs:Command=Render&MyParameter=Something

There was also a requirement for a link that directly exports the report as a PDF, using an additional query string parameter:

&rs:Format=PDF

So I thought just tag that on to the end of the main URL like this:

https://myportal.domain.com/_vti_bin/ReportServer?https://myportal.domain.com/Reports/Myreport.rdl&rs:Command=Render&MyParameter=Something&rs:Format=PDF

But when I tried this URL, instead of downloading a PDF file of the report I just got a 500 internal server error from the web server.  I tried adding an entry in my HOSTS file for myportal.domain.com to bypass the UAG server and connect directly to the SharePoint web server.  Then the link above worked OK and the download PDF popup box appeared.  So UAG is doing something to break that link.

The SharePoint ULS logs pointed to the problem.  Every time I got a 500 errors from Reporting Services I say errors like this in the logs:

Unexpected error in ProcessRequest: System.Net.CookieException: The ‘Value’=’2012,6,13,13,14,27,56,0’ part of the cookie is invalid.     at System.Net.Cookie.VerifySetDefaults(CookieVariant variant, Uri uri, Boolean isLocalDomain, String localDomain, Boolean set_default, Boolean isThrow)     at System.Net.CookieContainer.Add(Cookie cookie)     at Microsoft.ReportingServices.SharePoint.Soap.Utils.SetRelayRequestCookies(HttpWebRequest relayRequest, HttpRequest clientRequest)     at Microsoft.ReportingServices.SharePoint.Soap.RSBaseHttpHandler.ProcessRequest(HttpContext context) 2b0eb16a-e8df-4d6c-8cb8-3741011353f4

It looked as if there was some problem with a cookie with a value of 2012,6,13,13,14,27,56,0 – some kind of time stamp apparently.  I had a look at the site in Chrome and used the developer toolbar Resources tab to look at the cookies in the browser.  Sure enough there was a cookie called dwLastDetectionTimestamp with a value that looked like a timestamp with commas between the values.  I deleted this cookie manually from the browser and tried the URL again and it worked.  So it was that rogue cookie that was causing Reporting Services to fail.

Chrome Cookies

It turns out UAG injects a Javascript file called logoff.js into every web request that passes through it.  This Javascript file is what does the work of checking whether the activity timeout period has run out and whether to warn the end user of an impending auto-timeout.  It enters into an infinite recursive loop, checking that value of the cookie and if it’s null, setting it to be the current date and time, then checking to see if a certain period of time has elapsed.  Reporting Services for some reason inspects that value of this cookie but cannot understand it (because it belongs to UAG) and thus throws an exception.

The way round this is to override the UAG script and redefine that loop function to set the value of that cookie to be some non-null value, which deletes it from the cookie set.  I created a standard page in SharePoint to act as the target for Reporting Services reports.  The SharePoint page itself had a single Content Editor web part in it with a reference to my Javascript file which looks like this:

/* Strip the dwLastDetectionTimestamp cookie off the request and redirect it to the Report Server proxy */
function compareTimeStamps()
{
   $.cookie("dwLastDetectionTimestamp", null, { path: '/' }); // delete cookie
}

$(document).ready(function() {
  var FullUrl = window.location.href;
  var QueryString = FullUrl.split("?")[1];
  var NewServerUrl;
  if ((QueryString.match(/^https:\/\/myportal.mydomain.com.+$/ig))) {
    NewServerUrl = "https://myportal.mydomain.com/_vti_bin/ReportServer?" + QueryString;
    $.cookie("dwLastDetectionTimestamp", null, { path: '/' });
    window.location.href = NewServerUrl;
  }
});

To use this script you’ll need to have <script> tag references to JQuery and to the JQuery cookie plugin.  And of course you need to replace myportal.domain.com with the address of the root of your SharePoint site. The code in the script strips out the query string from the incoming request URL and checks to see if it’s a request to Report Server, and if so then it removes the cookie and redirects the browser to the Report Server proxy with the same query string.  Note the regular expression test (QueryString.match) which prevents the redirect happening when you are editing the page.  It will only redirect if the first thing after the question mark is a URL string.  The script also redefines the compareTimeStamps function within the script that UAG injects.  This is the function that is called continuously to check for auto-timeout.

In a report or a SharePoint page when you need to create a link that would use the URL of Report Server, you use instead the URL of the SharePoint page that holds this script. Add any query string parameters as required just as if you were going to the Report Server directly.

Advertisements

2 Comments »

  1. Thanks! Workaround worked for me.
    http://rrfreeman.blogspot.com

    Comment by Robert Freeman — August 1, 2012 @ 11:29 pm

  2. It’s actually a great and helpful piece of information. I’m happy that you shared this useful info with us.
    Please keep us up to date like this. Thanks for sharing.

    Comment by mobil pengantin — June 1, 2016 @ 6:35 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: