With the release of WCF RIA Services, Microsoft has made it much easier to implement multi-tier Silverlight based applications. Data resides in a database on the server and is accessible through the use of an ORM such as Entity Framework or OpenAccess. WCF RIA Services takes care of moving this data between the server and the client application by using Domain Services in conjunction with the ORM. As you may already know, Telerik Reporting includes a WCF based service responsible for rendering and serving up reports. This service however, is not based on WCF RIA Services, so a few steps must be taken in order to get the two working together. In this article, I’ll be showing you the necessary steps you need to take in order to get Telerik Reporting working within a WCF RIA Services based Silverlight application.
The application we will be creating actually looks pretty simple up front, but a lot will be going on behind the scenes. It will essentially display a list of Product Subcategories from the AdventureWorks database in a DataGrid. Each row in the DataGrid will contain a button that can be clicked to generate a report about which products are in that category.
You should be able to follow along with this article to create a working application. Please note that your environment will need to meet the following requirements before you can successfully create the application.
In this series of steps, we will create the initial application. This application will be based on the Silverlight Business Application template. This template provides us with a basic navigation application and support for RIA Services.
In the following steps we will create an ADO.NET Entity Data Model. This model will allow us to access data from a relational database quickly and easily through code. We will be able to use this model as the basis for a Domain Service we create in a future step.
In this section, we will extend the functionality of the AdventureWorksEntities ADO.NET Entity Data Model. We will be adding a custom query that returns products of a specific SubcategoryID.
public
partial
class
AdventureWorksEntities
{
public
System.Collections.Generic.List<Product> GetProductsBySubcategory(
int
subcategoryId)
{
return
this
.Products.Where(p => p.ProductSubcategoryID == subcategoryId).ToList();
}
}
This is where we will begin getting into WCF RIA Services. The next bit of code we generate is what's responsible for establishing communication between the Silverlight and ASP.NET applications. The Domain Service, as it's called, is responsible for controlling how the application accesses and uses our Entity Framework based model.
Now that we've created our model and added the domain service, it's time to begin creating our application. In the following steps, we will modify the business application to display a list of product subcategories in a datagrid on the home screen.
<
StackPanel
x:Name
=
"ContentStackPanel"
>
<
riaControls:DomainDataSource
x:Name
=
"subcategoryDomainDataSource"
AutoLoad
=
"True"
Width
=
"0"
Height
=
"0"
LoadedData
=
"subcategoryDomainDataSource_LoadedData"
QueryName
=
"GetProductSubcategoriesQuery"
>
<
riaControls:DomainDataSource.DomainContext
>
<
domain:AWDomainContext
/>
</
riaControls:DomainDataSource.DomainContext
>
</
riaControls:DomainDataSource
>
<
sdk:DataGrid
x:Name
=
"subcategoriesDataGrid"
Width
=
"800"
Height
=
"600"
AutoGenerateColumns
=
"False"
ItemsSource
=
"{Binding ElementName=subcategoryDomainDataSource, Path=Data}"
>
<
sdk:DataGrid.Columns
>
<
sdk:DataGridTextColumn
x:Name
=
"subcategoryNameColumn"
Binding
=
"{Binding Path=Name}"
Header
=
"Name"
Width
=
"200"
/>
<
sdk:DataGridTemplateColumn
x:Name
=
"subcategoryIDColumn"
Header
=
"Subcategory"
Width
=
"200"
>
<
sdk:DataGridTemplateColumn.CellTemplate
>
<
DataTemplate
>
<
Button
Content
=
"{Binding Path=ProductSubcategoryID}"
Click
=
"Button_Click"
/>
</
DataTemplate
>
</
sdk:DataGridTemplateColumn.CellTemplate
>
</
sdk:DataGridTemplateColumn
>
</
sdk:DataGrid.Columns
>
</
sdk:DataGrid
>
</
StackPanel
>
private
void
subcategoryDomainDataSource_LoadedData(
object
sender, LoadedDataEventArgs e)
{
if
(e.HasError)
{
System.Windows.MessageBox.Show(e.Error.ToString(),
"Load Error"
, System.Windows.MessageBoxButton.OK);
e.MarkErrorAsHandled();
}
}
private
void
Button_Click(
object
sender, System.Windows.RoutedEventArgs e)
{
}
As you may have noticed, the Button_Click event in the previous step currently contains no code. The primary goal of this application is to allow a user to click the button for a particular subcategory to generate a products report based on that subcategory. In this section, we will create the Telerik Report that will be displayed to the user.
Telerik Reports displayed in the Silverlight Report Viewer are actually generated on the server. Due to this, you will need to provide support for the Telerik Reporting WCF Service. This service allows the Silverlight Report viewer to request and retrieve generated Telerik Reports. This service is actually separate from those provided by RIA Services and should be thought of as a separate service.
Now that we have created our products listing report and enabled access to it via the Telerik Reporting Service, it's time to display that report in our application. In this series of steps, we will do just that.
<
Grid.RowDefinitions
>
<
RowDefinition
/>
<
RowDefinition
Height
=
"Auto"
/>
</
Grid.RowDefinitions
>
<
telerik:ReportViewer
x:Name
=
"ReportViewer1"
Grid.Row
=
"0"
ReportServiceUri
=
"../ReportService.svc"
Report
=
"ReportingDemo.Web.Reports.ProductsBySubcategoryReport, ReportingDemo.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
RenderBegin
=
"ReportViewer1_RenderBegin"
>
</
telerik:ReportViewer
>
<
Button
x:Name
=
"OKButton"
Content
=
"OK"
Click
=
"OKButton_Click"
Width
=
"75"
Height
=
"23"
HorizontalAlignment
=
"Right"
Margin
=
"0,12,0,0"
Grid.Row
=
"1"
/>
public
partial
class
ReportViewerDialog : ChildWindow
{
int
_subcategoryId;
public
ReportViewerDialog(
int
subcategoryId)
{
InitializeComponent();
_subcategoryId = subcategoryId;
}
private
void
OKButton_Click(
object
sender, RoutedEventArgs e)
{
this
.DialogResult =
true
;
}
private
void
ReportViewer1_RenderBegin(
object
sender, Telerik.ReportViewer.Silverlight.RenderBeginEventArgs args)
{
// specifies the subcategory as a report parameter to be used
// in the generation of the report
args.ParameterValues[
"subcategoryId"
] = _subcategoryId;
}
}
Button btn = sender
as
Button;
int
subcategoryId =
int
.Parse(btn.Content.ToString());
ReportViewerDialog viewer =
new
ReportViewerDialog(subcategoryId);
viewer.Show();
Whew, that was a lot to take in wasn't it? Well, now that you've completed all of these steps, you should be able to click the run button and the application should hopefully run successfully. Upon entering the home screen, you should see a listing of product subcategories generated via RIA Services. Each of these subcategories will have a corresponding button. Clicking the button will display our custom ReportViewerDialog. The silverlight report viewer contained in this dialog will send a request to the Telerik Reporting WCF service with the clicked SubcategoryID as a parameter. The Telerik Reporting WCF service will then generate and return a report to the report viewer to be displayed to the user.
Click here to download the source code.
Note: When running the demo application, make sure to set ReportingDemo.Web as the startup project. Otherwise, you might see the following dialog: