Simple WPF ReportViewer Example?

2 Answers 22 Views
Report Viewer - WPF
Bradley
Top achievements
Rank 1
Iron
Iron
Iron
Bradley asked on 06 Sep 2024, 01:52 AM

I downloaded the samples provided in GitHub and was very surprised and disappointed that there wasn't a single example of using the WPF ReportViewer.

What I'm doing seems trivial, but I'm stuck.  I've created a report in the stand-alone designer and saved it as a local file.  The report connects to SQL server.  I added the report server as per the instructions found at https://docs.telerik.com/reporting/embedding-reports/display-reports-in-applications/wpf-application/how-to-add-report-viewer-to-a-wpf-.net-core-project.  However, when I run the application, I get the following:

I've looked everywhere I can think of and have not found a solution to this simple problem.  Any help would be appreciated.

Thanks!

2 Answers, 1 is accepted

Sort by
0
Accepted
Lance | Senior Manager Technical Support
Telerik team
answered on 09 Sep 2024, 06:43 PM

Hello Bradley,

Thank you for sharing the error. What I think you're missing is the connection string in the WPF application's app config. The Report itself is referencing a table named "myReportTable", but where is that expecting to find it?

In the desktop Report Designer app, you might have used a SQL server data source that was defined in the global settings (i.e. a shared source), but the Report definition itself has no knowledge of the SQL server's connection string when it is being viewed in your WPF app. So, to address this, you need to have a connection string or some sort of connection in that WPF application, to the SQL server.

Walkthrough

As an example, let's start at the Report Designer. I have a named connection string "MyReadonlySamplesServer" for a SQL server where I have a tables named "samples":

If I write a report that uses that source, it appears on the available data sources list as an "existing" one:

Then, in the next step, you maybe used the Shared option?

WPF App Time

Okay, now you're done with the report and you have a report definition file (the tdrp), and you have it inside a WPF app. How is that WPF app supposed to know what SQL server to look for that samples table? This is typically done in the app.config file (if you don't have one, just add it to the project).

So, for example, if I want to use a report in the WPF app that I designed with the above Report Designer-defined source, it would look like this:

I recommend reading this documentation, it explains this a little further => Connect the SqlDataSource to Database - Telerik Reporting.

Note: the alternative is to embed the entire data source definition inside the report itself, but make sure it has the capability to connect to the SQL server from the WPF application (i.e. is port 1433 open? If it's a local source, does the WPF project have permissions to access it? etc)

Technical Support

If you have any further problems, please open a Support Ticket with your report attached, as well as the WPF app's settings, so we can have the engineering team take a close look at how it is configured.

  1. Go to https://www.telerik.com/account/support-center/contact-us/technical-support 
  2. Make the appropriate selections for Reporting
  3. Attach the relevant files and submit the ticket

Note: with a private support Ticket, it is important that you attach the relevant files so the team can assist more quickly.

Examples

You explicitly requested an example, so let me show you how to locate the one that you already have installed:

Go to C:\Program Files (x86)\Progress\Telerik Reporting 2024 Q3\Examples\CSharp\.NET 8\WpfIntegrationDemo and find the following project

You will find that project's app.config has a connection string that points to the AdventureWorks database (which is set up with your local DB when you installed Reporting)

Custom Demo

To help make this even easier for you, I've built you a very simple example. No theme switcher, just a simple report that connects to the SQL server I was mentioning earlier.

Open the attached project in Visual Studio, do a Rebuild and then deploy. You should see the same results as this screenshot

The SQL Server is defined in a connection string in app.config. The Report itself was designed to look for that connection string, because it was designed to.

Regards,
Lance | Senior Manager Technical Support
Progress Telerik

Stay tuned by visiting our roadmap and feedback portal pages, enjoy a smooth take-off with our Getting Started resources, or visit the free self-paced technical training at https://learn.telerik.com/.
Lance | Senior Manager Technical Support
Telerik team
commented on 09 Sep 2024, 06:45 PM

I just noticed that you are already being helped by the Reporting team in a Support Ticket. That's the best place to get 1:1 help, Dimitar is a wizard and can assist further.
Bradley
Top achievements
Rank 1
Iron
Iron
Iron
commented on 11 Sep 2024, 05:44 PM

Yes, although the response I got from Dimitar didn't solve the problem, with all the tidbits in this response, I finally figured it out.

Thanks!

Brad.

Lance | Senior Manager Technical Support
Telerik team
commented on 11 Sep 2024, 06:05 PM

Hi Brad, that's great news!  Please don't hesitate to reach out again for assistance.

Just to recap, the bottom line in this situation is that the WPF app needs to also have knowledge of the same SQL server connection that you were using in the standalone Report Designer.

The report itself usually doesn't have a full connection string in it unless you explicitly embedded it. This is typically not recommended because connection strings can contain secrets (it's okay if the connection string doesn't contain secrets and relies on Windows auth). So, the safest way to do it is the report only knows the name of the connection string it is looking for. No secrets needed, the host application handles that because it can be more secure.

This "knowledge" of the SQL server is done through a connection string in the WPF project's config. (app.config or app.json, it's the same). In my demo, I use a connection string named "MyReadonlySamplesServer" in both the standalone Report Viewer and the WPF project's app configuration.

Note: Rather than app config, you can also add connection string dynamically in code when it first starts up. This is more complicated and is reserved for situations when the connection string is encrypted and has to be decrypted on startup.


Bradley
Top achievements
Rank 1
Iron
Iron
Iron
commented on 11 Sep 2024, 06:15 PM

I'm still not 100% comfortable with the magic Telerik is doing to get the connection string, either from app.config or appsettings.json.  I would think, especially in a DI environment, that my code should be dictating where it's read from, and then I should tell Telerik that somehow, but... I can live with it the way it is.
Lance | Senior Manager Technical Support
Telerik team
commented on 11 Sep 2024, 07:18 PM

I can see where you're coming from, but there's no special stuff going on here. It's just checking the application configuration that's available everywhere in the app. For example:

var connection = ConfigurationManager.ConnectionStrings["SHARED_NAME_HERE"].ConnectionString;

 

In .NET 8, its even easier because of ConfigurationExtensions.GetConnectionString(IConfiguration, String) which results in the following kind of code:

public class MyClass
{
    public MyClass(IConfiguration config)
    {
        var connection = config.GetConnectionString("SHARED_NAME_HERE");
    }
}

I'm of course over simplifying, we have several fallbacks in case it isn't available in the config file.  Ultimately, its no different than getting any other values from the app configuration. This is why you were getting an error earlier, because Reporting couldn't find the named connection in any the app's configuration.

I hope this adds a little more insight!

 

Bradley
Top achievements
Rank 1
Iron
Iron
Iron
commented on 11 Sep 2024, 07:22 PM

Yeah, I'm fine with it.  I guess I would just expect some kind of "TelerikSettings" section in the appsettings file, rather than relying on the "ConnectionStrings" section, but there's certainly nothing wrong with it. :)
Bradley
Top achievements
Rank 1
Iron
Iron
Iron
commented on 12 Sep 2024, 09:38 PM | edited

Apparently I lied:  I'm not fine with it!

I just discovered that Telerik must use its own ConfigurationManager, since it doesn't appear to be honoring mine.  This is what I was saying about DI - to fit the MS pattern, I should be passing the ConfigurationManager (or an IOptions) to Telerik somehow.

What tripped me up is that I use the "UserSecrets" capability that facilitates development considerably.  Apparently the report viewer doesn't. 😒

Lance | Senior Manager Technical Support
Telerik team
commented on 13 Sep 2024, 12:25 PM

I see, you want the connection string in the user secrets. UserSecrets are pulled in as normal configurations items, so it's important to distinguish the ConnectionString section as not your typical configuration item, it has its own subsection.

So, it you set a UserSecret, I imagine it would need to be the exact same format with a ConnectonString top level section, and the individual strings as children. Can you confirm the user secret is being set like this?


It's important to remember that User Secrets are only for development, those secrets do not get deployed in a project when using publishing release builds.

When deploying/distribution, you need to use the environment's standard system for settings and secrets management. As an example, when deploying to Azure, you need to make sure any items that live in the ConnectionString section of the app config, get added on the Connection strings tab (the regular App setting tab is for top level items).

That being said, WPF is a very different situation than web application s which automatically handle these things, in a non-web app you need to preinitialize the user secrets https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-8.0&tabs=windows#user-secrets-in-non-web-applications 

This is all speculative at this point, I will need to discuss this with the reporting team to confirm that this approach will work the same in the non-REST service reporting engine. I will get you some advice from the team for this exact scenario.

Bradley
Top achievements
Rank 1
Iron
Iron
Iron
commented on 13 Sep 2024, 03:18 PM | edited

Whoa - hang on!  What I'm hearing is that you're going to ask your developers to implement reading configuration information from user secrets.  That is fundamentally the wrong approach.  Environment settings and "appsettings.json" are only conventions.  What if I'm using "mysettings.txt"? What if I want to read my settings from a database or a web service or a file share?  What if I have implemented my own configuration reader entirely?  Telerik Reporting should accept whatever implementation if IConfiguration I choose!  Ideally, when setting up my application, there should be one line that looks something like this:

settings.AddTelerikReporting(configuration);

This is true whether running a website, a console app, or a WPF app.

I don't want to be so arrogant as to say that's the only "right" way, but...

Lance | Senior Manager Technical Support
Telerik team
commented on 13 Sep 2024, 04:34 PM

Hi Brad, I just finished some experimentation between using appsettings.json and secrets.json.

I can confirm the following:

  • ✅ appsettings.json - ConnectionsString section's values are parsed
  • ❌ secrets.json - ConnectionStrings section is not parsed

First, to ensure the values are valid, I placed the ConnectionStrings section in the appsettings.json file, and confirmed everything works as expected at runtime. The values are present in the config and the report renders. 

Now, to test user secrets, I moved the ConnectionStrings section from appsettings.json to secrets.json. However, before running the app, I need to ensure that secrets.json are always being loaded by hard coding the "Environment=Development":

Next, I run the app and confirmed that the ConnectionStrings:MyReadonlySamplesServer value from secrets.json is available in the global IHost Configuration:

Finally, I verified the reporting engine cannot locate the connection string

Next Steps

I have passed this on to the Reporting team, this was unexpected, so they're looking into the matter further. 

Bradley
Top achievements
Rank 1
Iron
Iron
Iron
commented on 13 Sep 2024, 04:39 PM

Please, please, please have them look at the comment I made just prior to this.  Unless reporting accepts IConfiguration, the implementation is almost certain to be incorrect (or at the very least incomplete).  They are more than welcome to reach out to me about this, but at the end of the day, the only good result I can think of is that the developer using reporting has something like the following in their DI setup/configuration code:

settings.AddTelerikReporting(configuration);
Thanks a lot!
Lance | Senior Manager Technical Support
Telerik team
commented on 13 Sep 2024, 06:03 PM

Hi Brad,

I had not see your reply by the time I sent mine (I was still writing it when you replied). I hope that my reply clears up that I was referring to the engine being able to read any value from IConfiguration; not just secrets.json, or appsettings.json. 

Your recommendation of an extension method that allows the configuration to be passed to the engine is a good one. I have already let the team know, but so that it is trackable I have created a Feature Request on your behalf => Add support for injecting full configuration (telerik.com)

Note that this is really only an issue for desktop and console app situations. When using the REST service, you can give it full access to everything via a custom resolver or fiddling with the initial setup:

Bradley
Top achievements
Rank 1
Iron
Iron
Iron
commented on 13 Sep 2024, 06:05 PM

Perfect.  Thanks!
Lance | Senior Manager Technical Support
Telerik team
commented on 13 Sep 2024, 06:12 PM

I have asked them if there is a way to wire up the WPF ReportViewer to use an injected service like the REST engine uses. I'm envisioning something like this because it follows the pattern we use for DI everywhere else:

I need to hand this off to the Reporting team at this point. We're in territory that requires their deep internal knowledge of the engine for the desktop rendering, and I don't want to back you into a corner that doesn't end up working. The Reporting team will follow up in the feature request (this may take a couple days, not including the weekend).

Bradley
Top achievements
Rank 1
Iron
Iron
Iron
commented on 13 Sep 2024, 06:16 PM

Off hand that looks unnecessarily complicated, but hey - at least it would work! :)

0
Bradley
Top achievements
Rank 1
Iron
Iron
Iron
answered on 11 Sep 2024, 05:52 PM
Sure enough, the problem did have a trivial solution.  It just took me a while to understand more about shared connections, connection strings, and how Telerik found/used them.
Tags
Report Viewer - WPF
Asked by
Bradley
Top achievements
Rank 1
Iron
Iron
Iron
Answers by
Lance | Senior Manager Technical Support
Telerik team
Bradley
Top achievements
Rank 1
Iron
Iron
Iron
Share this question
or