viernes, 18 de septiembre de 2009

Telerik Reporting Integration to Silverlight


This time I'd like to talk about how to successfully integrate Telerik Reporting features to your Silverlight Solution. However I'd like get into more detail and give you the real thing, not only the nice picture as shown in Telerik site.

What I'd like to cover here is not only integrate the Reporting but also how successfully configure the whole thing and have it ready to deploy to your Preview / Production server.

Let's start... you will need three projects in your solution. One is the Silverlight project, another is the ASP.Net project that will be hosting the whole thing and finally a Library Application project for your reports.

I will assume you have already added a new report to your Report library and you followed the wizard and had your report filled with some data.

In your Silverlight project you will need to add a new page to show your report and to do so, you'll need to add a RadHtmlPlaceHolder Control (also from Telerik) and set the SourceUrl attribute to something like this:

<telerik:RadHtmlPlaceHolder SourceUrl="MySalesReport.aspx"> </telerik:RadHtmlPlaceHolder>

Add a new WebForm control to your ASP.NET project and named as "MySalesReport.aspx". Add a ReportViewer Control and add your report by populating the Report property in the Properties Panel (be sure to add a reference to your Report library project first). That's it!

That's it? What are you talking about? Here comes the tricky stuff...

Notice in the video that you need to add style properties for your form, body and html elements. But you also need to be sure your div tag has also width = 100%. If you don't do it, your report won't be 100% width in some browser like IE 8.

If you deploy the project as it is right now you'll notice you won't get any data. In order to fix this, first be sure to set "Copy Local" property equals true for your Telerik.Reporting.dll and Telerik.ReportViewer.WebForms.dll

If you used the report wizard that means your connection string is contained within your DataSetTableAdapter. One solution for this problem is to overwrite your connection string with the one specified in your web.config (in your ASP.NET project).

How to do that? You'll first need to add this to your Constructor after the InitializeComponents calling:

this.DataSource = null;

Then add a new handler for the event NeedDataSource. Here you will need to get your connection string and set it to your DataSetTableAdapter and then have it fill your DataSetTable and set this object as your report data source:

ConnectionStringSettings connSettings = ConfigurationManager.ConnectionStrings["SampleDB"];
if ((connSettings != null) && (connSettings.ConnectionString != null)) {
this.myDataSetTableAdapter1.Connection.ConnectionString = connSettings.ConnectionString;
}
this.myDataSetTableAdapter1.Fill(this.myDataSet.MyDataSetTable);
this.DataSource = this.myDataSet.MyDataSetTable;

One more thing, you'll notice that you can´t access to your DataSetTableAdapter's ConnectionString property to change it.

This is because this property is a private property. However your DataSetTableAdapter class definition is partial. That means you can add modify this class, so add a new partial class for you Adapter after your Report class definition and add a new property to get access to your ConnectionString.

Now, that's really it. You are good to go.

martes, 15 de septiembre de 2009

All about App.Config

It's been a long time since I don´t write anything. I've been a little bit busy working and jumping from Silverlight to Windows Services, Installers, Telerik Controls in ASP.NET, etc.

While working, I've found out an interesting challenge. How to access another's application app.config file and be able to read and write to it?

Think in this scenario for a second, you have a Windows Service (not UI if you are not familiar with Windows Services) that needs to read some parameters from the configuration file. And the configuration is really complex that you prefer to have a Windows Form Application to help you set all the values.

That's exactly what I want to accomplish. So here we go. You'll need to add System.Configuration to your project's reference.

To read a value from the app.config it's the basic thing and it's very easy:
string value = ConfigurationManager.AppSetttings["key"];

To write a value it's not so easy, at least it doesn't work the other way around. You cannot do something like:
ConfigurationManager.AppSettings["key"] = "this is wrong" <- WRONG!
This is how you do it:

// Open App.Config
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

// Add an Application Setting.
config.AppSettings.Settings.Add("date", DateTime.Now.ToShortString());

// Update an Application Setting.
config.AppSettings.Settings["key"] = "this is correct";

// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);

// Force a reload of a changed section.
ConfigurationManager.RefreshSection("appSettings");


In order to access another's application app.config you need to know the file location. For the problem I have exposed I'm writing the Windows Service location to Registry using System.Reflection.Assembly.GetExecutingAssembly().Location. Then in my configuration application I retrieve this value and use it this way:

ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
filemap.ExeConfigFilename = Location; //(this is the location of the app.config I'm trying to access)

Configuration config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);

AppSettingsSection appsettings = config.AppSettings;

appsettings.Settings["key"] = "value";

config.Save();

So now we are able to access the app.config, read and write to it even if it's another's application config file.
Hope this is worthy!

Important Note:

When debugging, you won't get anything written in your app.config.

Actually if you "Quick Watch" your config variable you will notice that is pointing to a file named something like: ApplicationName.vshost.exe.config.

Don't worry I can assure you this code works!