Monday, March 26, 2012

Report Viewer Reverse Proxy

I was wondering if anybody knew anything about the ReportUrl QueryString
parameter and if it requires a certain format.
I'm currently attempting to write a reverse-proxy HttpHandler for accessing
reports in SSRS 2005. I'm doing it this way for three reasons: 1) We have to
use VS2003, 2) Users don't have direct access to the database server (and
thus SSRS via URL access), and 3) I like the report viewer and want to avoid
cloning it with my own. I am very close to succeeding and promise, if
successful, to post the resulting code here.
I've currently got the main page loading, the wait page loading, and all
images loading, but I'm getting a (500) Internal Server Error when the actual
report attempts to load in the iframe. The event log shows the following
info:
Exception information:
Exception type: HttpHandlerInputException
Exception message: ReportUrl
I've made my own HttpHandler and also named it
Reserved.ReportViewerWebControl (via web.config), so the only difference
between my URL and a normal URL is the addition of a virtual directory name.
It looks like this:
http://ServerName/VirtualDirectoryName/ReportServer/Reserved.ReportViewerWebControl.axd?OpType=DocMapReport&ClientController=ClientControllerReportViewerControl&ReportUrl=%2fVirtualDirectoryName%2fReportServer%2fReserved.ReportViewerWebControl.axd%3fExecutionID%3dmjuze0ni4lyf4v55cebmh2mr%26ControlID%3d03b34cbd-599e-4c7d-a19d-854cd1c7eec6%26Culture%3d1033%26UICulture%3d9%26ReportStack%3d1%26OpType%3dReportArea%26Controller%3dClientControllerReportViewerControl%26PageNumber%3d1%26ZoomMode%3dPercent%26ZoomPct%3d100%26ReloadDocMap%3dtrue%26EnableFindNext%3dFalse%26LinkTarget%3d_top
Whew. If I take out the virtual directory name it works fine, but that's
because it now references the actual reporting services installed locally on
my box (it gets an rsExecutionNotFound error). Does anybody know if there's
a known issue with sticking a virtual directory in the ReportUrl? Thanks in
advance for the info, and please chime in if you have any suggestions.
- DaveHello Dave,
From your description, you are developing a custom httphandler that will
help get SSRS report from SSRS reportserver and display to other client
user through ASP.NET web application, however, you are encountering some
problem with the reportURL used in the handler, correct?
As for your own custom handler, what is the code logic of it, do you simply
copy the Microsoft.Reporting.WebForms.HttpHandler(built-in) class's code
logic? Based on my research, the following URL
========/ASPNET/V2/WebSites/PostPageSite/Reserved.ReportViewerWebControl.axd?OpType=DocMapReport&ClientController=ClientControllerReportViewer1&ReportUrl=/ASPNE
T/V2/WebSites/PostPageSite/Reserved.ReportViewerWebControl.axd%3fReportSessi
on%3dr1hwjmr1e5e5moygaqmwpu45%26ControlID%3d0f59883b-da9b-4044-add7-99bcd496
eeb4%26Culture%3d2052%26UICulture%3d1033%26ReportStack%3d1%26OpType%3dReport
Area%26Controller%3dClientControllerReportViewer1%26PageNumber%3d1%26ZoomMod
e%3dPercent%26ZoomPct%3d100%26ReloadDocMap%3dtrue%26EnableFindNext%3dFalse%2
6LinkTarget%3d_to
=============
is dedicated for the Microsoft.Reporting.WebForms.HttpHandler handler and
is not documented. IMO, if you want to write a custom handler than will
retrieve report from backend SSRS server and stream it to front end client,
you can consider use the SSRS 2005's webservice to request and render
report. Actually, the ReportViewer control internally also use the SSRS
2005 webservice to access the report.
If you do want to inspect the ReportUrl used by ReportViewer control and
the axd handler, you may use reflector to investigate the reportviewer and
the handler's code. I've performed some view and find that it is the ""
class which do the DocmapReport render task. It has the following code
logic to parse the querystring:
#In the "Microsoft.Reporting.WebForms.DocMapReportPageOperation" class
==============public override void PerformOperation(NameValueCollection urlQuery,
HttpResponse response)
{
DocMapReportPage page1 = new DocMapReportPage();
page1.ReportAreaUrl = HandlerOperation.GetAndEnsureParam(urlQuery,
"ReportUrl");
if
(!page1.ReportAreaUrl.StartsWith(HttpHandler.HandlerUri.Uri.PathAndQuery,
StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentOutOfRangeException("ReportUrl");
}
page1.ClientController = HandlerOperation.GetAndEnsureParam(urlQuery,
"ClientController");
HandlerOperation.EnsureValidJavascriptIdentifier(page1.ClientController);
HttpContext.Current.Server.Transfer(page1, true);
}
==============
Hope this helps some.
Sincerely,
Steven Cheng
Microsoft MSDN Online Support Lead
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.|||Thank you, thank you, thank you! Your post gave me the exact clue I needed -
namely that the ReportUrl parameter is validated in some way and URL paths
are compared. I made some adjustments in my code to kind of "trick" SQL
Server into thinking it was using a ReportUrl whose path matched the server's
URL and it worked great!
For your info, I'm using HttpWebRequest and HttpWebResponse objects to
create a kind of reverse proxy server. I was thinking of abandoning this
path and going with the web service, but I originally tried to access things
this way because I liked the Report Viewer and didn't want to write code to
"clone" its toolbar. From what I've read in the docs, if you use web service
access to get your report you have to write your own viewer GUI. I
originally thought I could save some time by writing a quick and dirty
reverse proxy, but quickly found I was in for some whole new troubles.
Anyway, my code is now properly retrieving the report and displaying it.
The export seems to missing a response header (quick fix), and the print
button returns an error, but as soon as I figure those out I'll post the code
here. Thanks again for your help. I'm also going to investigate the use of
the reflector to view code, thanks for the tip.
- Dave|||That's great Dave,
I'm glad that the information is of assistance.
Have a nice day!
Sincerely,
Steven Cheng
Microsoft MSDN Online Support Lead
This posting is provided "AS IS" with no warranties, and confers no rights.|||In case you're interested, I posted the code that ended up working for me as
a new message named "Using SSRS Viewer in VS2003 with Reverse Proxy". Thanks
again for your help.
"Steven Cheng[MSFT]" wrote:
> That's great Dave,
> I'm glad that the information is of assistance.
> Have a nice day!
>
> Sincerely,
> Steven Cheng
> Microsoft MSDN Online Support Lead
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
>sql

No comments:

Post a Comment