Reputation: 2099
I have an application that serves SSRS reports. A given report is accessed in the following way:
https://reportserver.com/reportname
Upon clicking View Report, a postback is submitted to the report server with the user-defined parameters. I need to grab these user-defined parameters and parse them as a URL string.
Desired result: https://reportserver.com/reportname?param1=foo¶m2=bar
I found this doc that gets me close to what I need. This method should allow me to grab all visible parameters and parse them myself, but I need hidden parameters as well.
How can I build this parameter string? We're using JavaScript/jQuery in the front end so it may be possible to grab this client-side before the POST, but I haven't found a way of doing this either.
Upvotes: 2
Views: 1148
Reputation: 3195
I've created URLs for reports with parameters 3 different ways. A combination of the the first two may get you closer to solving your problem.
Use custom code in the report properties.
Public Function ShowParameterValues(ByVal parameter As Parameter) As String
Dim s as String = String.Empty
Try
If parameter.IsMultiValue then
s = "Multivalue: "
For i as integer = 0 to parameter.Count-1
s = s + CStr(parameter.Value(i)) + " "
Next
Else
s = "Single value: " + CStr(parameter.Value)
End If
Return s
Catch ex As Exception
Return "error"
End Try
End Function
OR
Use a hyperlink in the report.
=Globals!ReportServerUrl + "/ReportServer?"
+ Replace(Globals!ReportFolder, " ", "+") + "%2f"
+ Replace(Globals!ReportName, " ", "+") + "&rs:Command=Render"
+ "&boolean_value=" + CStr(Parameters!boolean_value.Value)
+ "&single_value_parameter=" + Parameters!single_value_parameter.Value
+ "&multi_value_parameter=" + Join(Parameters!multi_value_parameter.Value, "&multi_value_parameter=")
+ IIf(IsNothing(Parameters!week_date_start.Value), "&week_date_start:isnull=True", "&week_date_start=" & Format(Parameters!week_date_start.Value, Variables!FormatDate.Value))
+ IIf(IsNothing(Parameters!week_date_end.Value), "&week_date_end:isnull=True", "&week_date_end=" & Format(Parameters!week_date_end.Value, Variables!FormatDate.Value))
Also, I usually add this as a report variable and then you can have a standard textbox for the footer that doesn't have to change.
=Variables!UrlReportWithParameters.Value
OR
Use the execution log. Check out the column URL_Report_Filtered
--Purpose: to search the reporting services execution log
DECLARE @all_value AS VARCHAR(10) = '<ALL>';
DECLARE @LogStatus AS VARCHAR(50) = '<ALL>';
DECLARE @ReportFolder AS VARCHAR(450) = 'Testing';
DECLARE @ReportName AS VARCHAR(450) = '<ALL>';
DECLARE @UserName AS VARCHAR(260) = '<ALL>';
DECLARE @GroupByColumn AS VARCHAR(50) = 'Report Folder';
DECLARE @StartDate AS DATETIME = NULL;
DECLARE @EndDate AS DATETIME = NULL;
WITH
report_users
AS
(
SELECT
[UserID]
, [UserName]
, [SimpleUserName] = UPPER(RIGHT([UserName], (LEN([UserName])-CHARINDEX('\',[UserName]))))
FROM
[dbo].[Users]
)
,
report_catalog
AS
(
SELECT
rpt.[ItemID]
, rpt.[CreatedById]
, rpt.[ModifiedById]
, rpt.[Type]
, rpt.[Name]
, [ReportName] = rpt.[Name]
, rpt.[Description]
, rpt.[Parameter]
, [CreationDate] = CONVERT(DATETIME, CONVERT(VARCHAR(11), rpt.[CreationDate], 13))
, [ModifiedDate] = CONVERT(DATETIME, CONVERT(VARCHAR(11), rpt.[ModifiedDate], 13))
, [ReportFolder] = SUBSTRING(rpt.[Path], 2, LEN(rpt.[Path])-LEN(rpt.[Name])-2)
, rpt.[Path]
, [URL_ReportFolder] = 'http://' + Host_Name() + '/Reports/Pages/Report.aspx?ItemPath=%2f' + SUBSTRING(rpt.[Path], 2, LEN(rpt.[Path])-LEN(rpt.[Name])-2) + '&ViewMode=List'
, [URL_Report] = 'http://' + Host_Name() + '/Reports/Pages/Report.aspx?ItemPath=%2f' + SUBSTRING(rpt.[Path], 2, LEN(rpt.[Path])-LEN(rpt.[Name])-2) + '%2f' + rpt.[Name]
, [ReportDefinition] = CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), rpt.[Content]))
, [HostName] = Host_Name()
FROM
[dbo].[Catalog] AS rpt
WHERE
1=1
AND rpt.[Type] = 2
)
SELECT
[GroupBy1] =
CASE
WHEN @GroupByColumn = 'Report Name' THEN rpt.[ReportName]
WHEN @GroupByColumn = 'Report Folder' THEN rpt.[ReportFolder]
WHEN @GroupByColumn = 'User Id' THEN usr.[SimpleUserName]
ELSE '<N/A>'
END
, rpt.[Path]
, rpt.[ReportFolder]
, rpt.[Name]
, rpt.[URL_ReportFolder]
, rpt.[URL_Report]
, [URL_Report_Filtered] = rpt.[URL_Report] + '&rs:Command=Render&' + CONVERT(VARCHAR(max), el.[Parameters])
, [UserName] = usr.[SimpleUserName]
, el.[Status]
, el.[TimeStart]
, el.[RowCount]
, el.[ByteCount]
, el.[Format]
, el.[Parameters]
, [TotalSeconds] = CONVERT(CHAR(8),DATEADD(ms,(el.[TimeDataRetrieval] + el.[TimeProcessing] + el.[TimeRendering]),0),108)
, [TimeDataRetrieval] = CONVERT(CHAR(8),DATEADD(ms,el.[TimeDataRetrieval],0),108)
, [TimeProcessing] = CONVERT(CHAR(8),DATEADD(ms,el.[TimeProcessing],0),108)
, [TimeRendering] = CONVERT(CHAR(8),DATEADD(ms,el.[TimeRendering],0),108)
, [OrderbyDate] = CAST([TimeStart] AS DATETIME)
FROM
report_catalog AS rpt
LEFT JOIN [dbo].[ExecutionLog] AS el ON el.[ReportID] = rpt.[ItemID]
LEFT JOIN report_users AS usr ON el.[UserName] = usr.[UserName]
WHERE
1=1
AND (@all_value IN(@LogStatus) OR el.[Status] IN(@LogStatus))
AND (@all_value IN (@ReportFolder) OR rpt.[ReportFolder] IN(@ReportFolder))
AND (@all_value IN(@ReportName) OR rpt.[ReportName] IN(@ReportName))
AND (@all_value IN(@UserName) OR usr.[SimpleUserName] IN(@UserName))
AND (@StartDate IS NULL OR CONVERT(DATETIME, CONVERT(VARCHAR(11), el.[TimeStart], 13)) >= @StartDate)
AND (@EndDate IS NULL OR CONVERT(DATETIME, CONVERT(VARCHAR(11), el.[TimeStart], 13)) <= @EndDate)
Upvotes: 3
Reputation: 2099
I got it working. Fair warning: I'm new to ASP.NET so this is likely not an ideal solution.
I added an event handler to the report viewer control's code behind. This queries the execution log, grabbing the parameters selected most recently by the user. It is meant to be triggered when a button called "Save Report" is clicked. If you try to handle this with a Load
or PreRender
event handler it will fire before the row has a chance to insert into the database, giving you the result of the user's second most recent execution parameters.
Define the Button (.ascx file)
<asp:LinkButton ID="SaveReportButton" runat="server" title="Save this Report"></asp:LinkButton>
Add event handler to code behind (.ascx.vb file)
Protected Sub SaveReportButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SaveReportButton.Click
Dim conn As New SqlConnection(<connection string here>)
Dim cmd As New SqlCommand("SELECT TOP 1 Parameters FROM [ReportServer].[dbo].[ExecutionLogStorage] WHERE <qualify on user, timestamp, etc. here>", conn)
cmd.Parameters.AddWithValue(<query parameter here>)
conn.Open()
Dim result = cmd.ExecuteScalar()
' Prevents NullReferenceException from result.ToString() in case no result is found
If (result IsNot Nothing)
' Redirect based on parameter string retrieved from log
Response.Redirect(HttpContext.Current.Request.Url.AbsoluteUri & "?" & result.ToString())
End If
conn.Close()
End Sub
Call postback from JavaScript on button click
<li>
<a href=\'javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(<reference SaveReportButton with appropriate arguments>)\' id="SaveReportButton" title="Save Report">
Save Report
</a>
</li>
Documentation on WebForm_DoPostBackWithOptions()
and WebForm_PostBackOptions()
is sparse, but a colleague has already done it this way so I followed suit for consistency's sake because it works.
Upvotes: 3