diff --git a/RdlEngine/Definition/ReportParameter.cs b/RdlEngine/Definition/ReportParameter.cs index 8a25048c..41b869bf 100644 --- a/RdlEngine/Definition/ReportParameter.cs +++ b/RdlEngine/Definition/ReportParameter.cs @@ -495,10 +495,16 @@ private object GetDataValueFromDisplay(object dvalue) /// /// The runtime value of the parameter. + /// Prefer using GetValueAsync() to avoid synchronous blocking on an async call. /// public object Value { - get { return _rp.GetRuntimeValue(this._rpt); } + get + { + // HACK: async - synchronous wrapper needed for property getter; + // use GetValueAsync() when an async context is available. + return Task.Run(async () => await _rp.GetRuntimeValue(this._rpt)).GetAwaiter().GetResult(); + } set { if (this.MultiValue && value is string) @@ -513,6 +519,15 @@ public object Value } } + /// + /// Asynchronously gets the runtime value of the parameter. + /// Prefer this over the synchronous Value getter when an async context is available. + /// + public async Task GetValueAsync() + { + return await _rp.GetRuntimeValue(this._rpt); + } + /// /// Take a string and parse it into multiple values /// diff --git a/RdlViewer/RdlViewer.cs b/RdlViewer/RdlViewer.cs index 05c00c07..1885a7b6 100644 --- a/RdlViewer/RdlViewer.cs +++ b/RdlViewer/RdlViewer.cs @@ -900,7 +900,7 @@ public async Task SaveAs(string FileName, Majorsilence.Reporting.Rdl.OutputPrese if (!(type == OutputPresentationType.PDF || type == OutputPresentationType.PDFOldStyle || type == OutputPresentationType.TIF || type == OutputPresentationType.TIFBW)) { - var ld = GetParameters(); // split parms into dictionary + var ld = await GetParameters(); // split parms into dictionary await _Report.RunGetData(ld); // obtain the data (again) } try @@ -1445,7 +1445,7 @@ private async Task GetPages(Report report) { Pages pgs = null; - var ld = GetParameters(); // split parms into dictionary + var ld = await GetParameters(); // split parms into dictionary try { @@ -1479,8 +1479,33 @@ private async Task GetPages(Report report) return pgs; } - private IDictionary GetParameters() + private async Task GetParameters() { + // If we have a loaded report with user parameters, use those runtime values + // instead of the _Parameters dictionary which may be stale + if (_Report != null && _Report.UserReportParameters != null && _Report.UserReportParameters.Count > 0) + { + Dictionary runtimeParams = new Dictionary(); + foreach (UserReportParameter urp in _Report.UserReportParameters) + { + // Always include user parameters, even when the value is null, so that + // stale values from _Parameters cannot override user-visible parameters. + runtimeParams[urp.Name] = await urp.GetValueAsync(); + } + // Merge with any parameters from _Parameters that aren't in UserReportParameters + if (_Parameters != null) + { + foreach (DictionaryEntry kvp in _Parameters) + { + string key = kvp.Key.ToString(); + if (!runtimeParams.ContainsKey(key)) + { + runtimeParams[key] = kvp.Value; + } + } + } + return runtimeParams; + } return _Parameters; }