This is a migrated thread and some comments may be shown as answers.

Set connection string dynamically and access report parameter values

9 Answers 337 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Scott Waye
Top achievements
Rank 2
Veteran
Iron
Scott Waye asked on 24 Jun 2015, 07:55 PM

Hi,

 I'm setting the connection string dynamically through the Resolve method, but I also need to access the actual report parameter values.  It seems that this is impossible as the way to do it is through the NeedDataSource handler, but that is not called as the data source has already been set by the code that sets up the connection string.  Is there a way to do this?

9 Answers, 1 is accepted

Sort by
0
Stef
Telerik team
answered on 29 Jun 2015, 08:33 AM
Hello Scott,

You can use an expression which will show you the processing values of report parameters. You can also use the report's ItemDataBinding event to get the processing values.

In order to provide you more accurate suggestions, please elaborate on the reason to access the running values in the report.

Regards,
Stef
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Scott Waye
Top achievements
Rank 2
Veteran
Iron
answered on 30 Jun 2015, 04:31 PM

Thanks Stef,

 I have 2 requirements for the report parameters:

1. The reports run against a multitenant system and I need to validate the parameters chosen conform to the authenticated tenant.  Your suggestion of the ItemDataBinding event seems to be working fine for this purpose, thanks.

 

2. I need to override and add parameters at run time that are not allowed to be specified by the user.  For example from the authenticated user I can get a tenant key which needs to be supplied to the report.  The user must not be allowed to specify this value as it would mean they could access another tenant's data.  I can't seem to find a suitable place to do this, any suggestions?

 

Thanks,

Scott

0
Stef
Telerik team
answered on 03 Jul 2015, 01:54 PM
Hi Scott,

If you are using the Silverlight ReportViewer, you can pass parameters' values  through the viewer's ApplyParameters event handler:
private void ReportViewer1_ApplyParameters(object sender, Telerik.ReportViewer.Silverlight.ApplyParametersEventArgs args)
       {
           args.ParameterValues["country"] = new object[] { "France", "Australia" };
       }

If you meed to perform the logic on the server, you can use a custom Report Resolver for the Reporting WCF service. In the resolver's Resolve method you can modify the report definition and its ReportParameters collection. As a result the Resolve method must return a UriReportSource.
Consider the example in this forum thread.

Regards,
Stef
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Scott Waye
Top achievements
Rank 2
Veteran
Iron
answered on 03 Jul 2015, 04:05 PM

Hi, I'm using the HTML viewer.  I have the following created in the HTML page:

<script type="text/javascript">
        $(document).ready(function () {
            $("#reportViewer1")
                .telerik_ReportViewer({
                     
                    // The URL of the service which will serve reports.
                    // The URL corresponds to the name of the controller class (ReportsController).
                    // For more information on how to configure the service please check http://www.telerik.com/help/reporting/telerik-reporting-rest-conception.html.
                    serviceUrl: "api/reports/",
 
                    // The URL for the report viewer template. The template can be edited -
                    // new functionalities can be added and unneeded ones can be removed.
                    // For more information please check http://www.telerik.com/help/reporting/html5-report-viewer-templates.html.
                    templateUrl: 'ReportViewer/templates/telerikReportViewerTemplate-9.0.15.422.html',
 
                    //ReportSource - report description
                    reportSource: {
 
                        // The report can be set to a report file name (trdx report definition)
                        // or CLR type name (report class definition).
                        report: "Reports/LaytimeCalculation.trdx",
 
                        // Parameters name value dictionary
                        parameters: {
                            claimKey : 177,dateFormat : "{0:dd/MM/yy}"
                        }
                    },
 
                    // Specifies whether the viewer is in interactive or print preview mode.
                    // PRINT_PREVIEW - Displays the paginated report as if it is printed on paper. Interactivity is not enabled.
                    // INTERACTIVE - Displays the report in its original width and height without paging. Additionally interactivity is enabled.
                    viewMode: telerikReportViewer.ViewModes.INTERACTIVE,
 
                    // Sets the scale mode of the viewer.
                    // Three modes exist currently:
                    // FIT_PAGE - The whole report will fit on the page (will zoom in or out), regardless of its width and height.
                    // FIT_PAGE_WIDTH - The report will be zoomed in or out so that the width of the screen and the width of the report match.
                    // SPECIFIC - Uses the scale to zoom in and out the report.
                    scaleMode: telerikReportViewer.ScaleModes.SPECIFIC,
 
                    // Zoom in and out the report using the scale
                    // 1.0 is equal to 100%, i.e. the original size of the report
                    scale: 1.0,
 
                    ready: function () {
                        this.refreshReport();
                    },
                });
        });
    </script>

Where you can see the dateFormat is set to dd/MM/yy.  I then have an IReportResolver impementation (based on the one which does the connection string setting) which in the Resolve method attempts to update this  parameter using this code:

ReportSource CreateInstanceReportSource(IReportDocument report, ReportSource originalReportSource)
       {
           var instanceReportSource = new InstanceReportSource {ReportDocument = report};
           instanceReportSource.Parameters.AddRange(originalReportSource.Parameters);
           var reportx = report as Report;
           AddOrSetMissingMandatoryParams(instanceReportSource.Parameters);
           // TODO validate here
           if (reportx != null)
           {
               reportx.ItemDataBinding += (sender, args) =>
               {
                   var processingReport = (Telerik.Reporting.Processing.Report)sender;
                   // throw new SecurityException();
               };
           }
           return instanceReportSource;
       }
 
 
       void AddOrSetMissingMandatoryParams(ParameterCollection reportParams)
       {
           var dateFormat = reportParams.FirstOrDefault(rp => rp.Name == SpecialParameters.DateFormat);
           if (dateFormat == null)
           {
               reportParams.Add(new Telerik.Reporting.Parameter
               {
                   Name = SpecialParameters.DateFormat,
                   Value = "{0:dd/MMM/yy}" //TODO  user.ClientAccountUser.PreferredDateFormat));
               });
           }
           else
           {
               dateFormat.Value = "{0:dd/MMM/yy}"
           }
       }

Here it is attempting to override the value passed in the JSON with a different date format, but this is not used and the report textbox which has a databinding for the Format to the report parameter (= Parameters.dateFormat.Value) displays the date in the dd/MM/yy format.

 

 

0
Stef
Telerik team
answered on 03 Jul 2015, 05:04 PM
Hi Scott,

The custom resolver will be called 3 times initially - to register and the report, to resolve the viewer's reportSource.report string to a ReportSource and then to apply the viewer's reportSource.parameters. Thus the value set in the Resolve method is overridden by the client value for the report parameter.

In the custom resolver's Resolve method you can set values of hidden report parameters by working directly with the report instance's ReportParameters collection. This includes sending information about the user in the report.
About changing the user's selected DateTime format, this can be done by using two report parameters and an expression checking which of them should be used. One of the report parameters can be hidden and set in the Resolve method, and the other value can be set at the client. The idea is illustrated in the attached TRDX file - switch the ControlParameter value to change the format of the TextBox item.


Let me know if I have misunderstood the scenario.

Regards,
Stef
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Scott Waye
Top achievements
Rank 2
Veteran
Iron
answered on 03 Jul 2015, 05:54 PM

Hi, thanks for the info on the ReportParameters collection, that works fine when the user has not supplied a value.  However lets change the example to make it clearer.  Instead of dateFormat, lets have an int which is tenantKey.  This is still a hidden parameter and defines which subset of data the user can access.  Normally this is a hidden parameter and is not supplied in the JSON so the server can set the value.  However as the value is supplied from the client, it's possible the user can manipulate the JSON (using Fiddler for example) and attempt to supply values that they should not have access to.  It's in this scenario that the server needs to be able to overwrite the supplied value and this is where I am currently stuck.  Adding more parameters to control/switch the values does not help as the user can manipulate those. 

 

I've taken your example and changed to suit this.  The user now tries to hack by specifies a value using JSON from the client thus:

 

reportSource: {
 
    // The report can be set to a report file name (trdx report definition)
    // or CLR type name (report class definition).
    report: "Reports/tenantKey.trdx",
 
    // Parameters name value dictionary
    parameters: {
        tenantKey : 1
    }
},

And the server tries to correct the manipulated value but it cant:

 

ReportSource CreateInstanceReportSource(IReportDocument report, ReportSource originalReportSource)
{
    var instanceReportSource = new InstanceReportSource {ReportDocument = report};
    instanceReportSource.Parameters.AddRange(originalReportSource.Parameters);
    var concreteReport = report as Report;
    // TODO validate here
    if (concreteReport != null)
    {
        AddOrSetMissingMandatoryParams(concreteReport.ReportParameters);
        concreteReport.ItemDataBinding += (sender, args) =>
        {
            var processingReport = (Telerik.Reporting.Processing.Report)sender;
            // throw new SecurityException();
        };
    }
    return instanceReportSource;
}
 
 
void AddOrSetMissingMandatoryParams(ReportParameterCollection reportParams)
{
    var tenantKey = reportParams.FirstOrDefault(rp => rp.Name == "tenantKey");
    tenantKey.Value = 2;
}

I can't attach the trdx file here, but its pretty short:

 

<?xml version="1.0" encoding="utf-8"?>
<Report Width="6.5in" Name="Report1" xmlns="http://schemas.telerik.com/reporting/2012/3.8">
  <Items>
    <DetailSection Height="2in" Name="detailSection1">
      <Items>
        <TextBox Width="2in" Height="0.4in" Left="2.in" Top="0.8in" Value="= Parameters.tenantKey.Value" Name="textBox1">
          <Style>
            <Font Size="16pt" Bold="True" />
          </Style>
        </TextBox>
      </Items>
    </DetailSection>
  </Items>
  <StyleSheet>
    <StyleRule>
      <Style>
        <Padding Left="2pt" Right="2pt" />
      </Style>
      <Selectors>
        <TypeSelector Type="TextItemBase" />
        <TypeSelector Type="HtmlTextBox" />
      </Selectors>
    </StyleRule>
  </StyleSheet>
  <PageSettings>
    <PageSettings PaperKind="Letter" Landscape="False" ColumnCount="1" ColumnSpacing="0in">
      <Margins>
        <MarginsU Left="1in" Right="1in" Top="1in" Bottom="1in" />
      </Margins>
    </PageSettings>
  </PageSettings>
  <ReportParameters>
    <ReportParameter Name="tenantKey" Type="Integer" Visible="True" AutoRefresh="True">
      <Value>
        <String></String>
      </Value>
    </ReportParameter>
  </ReportParameters>
</Report>

Hope that makes it clear.

 

Thanks for your help.

0
Stef
Telerik team
answered on 06 Jul 2015, 03:34 PM
Hi Scott,

The value of the tenantKey parameter will be included in requests. Thus consider using an encrypted value, which is decrypted only in the report's data retrieval method. the value should be set in the custom resolver's Resolve method. The value can have expiration time and other security settings per your requirements.

If the end-user tries to send a new value with the request for the report, it will override the value set in the resolver's Resolve method, but if the new value not valid, the data retrieval method can be implemented to not fetch data or else.

Regards,
Stef
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Scott Waye
Top achievements
Rank 2
Veteran
Iron
answered on 06 Jul 2015, 03:57 PM
HI Stef,  Thanks for the suggestion.  Just to conclude then, there is no entry point in the controller (derived from ReportsControllerBase) or the resolver where the parameter values can be overridden?
0
Accepted
Stef
Telerik team
answered on 07 Jul 2015, 08:36 AM
Hi Scott,

The initial request for sending parameters' values from the client can be caught in the services GetParameters method. Consecutive requests are directly sent as requests for a new report instance, and contain information about the report and the new parameters values.

Thus the most secure approach is to use encrypted values, which the end-user cannot edit or change that easily, and which values are validated on the server e.g., in the data retrieval method

Regards,
Stef
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
General Discussions
Asked by
Scott Waye
Top achievements
Rank 2
Veteran
Iron
Answers by
Stef
Telerik team
Scott Waye
Top achievements
Rank 2
Veteran
Iron
Share this question
or