Click here to Skip to main content
15,867,453 members
Articles / Web Development / ASP.NET
Article

Integrate Reporting Services with Silverlight and RIA Services

Rate me:
Please Sign up or sign in to vote.
5.00/5 (8 votes)
28 Jul 2010CPOL3 min read 91.8K   2.3K   52   24
Integrate Reporting Services with your Silverlight Line-of-Business applications.

Introduction

One of the most wanted future features in Silverlight is the possibility to create business reports using Reporting Services. In this article, I will show how to use the existing Reporting Services technology with Silverlight and RIA Services combination.

Background

I assume that the reader has some basic to intermediate level knowledge in Silverlight and RIA Services and C#, also some knowledge about WCF and the Entity Framework.

Using the Code

The first thing to do is create a Silverlight Application in Visual Studio 2010. I used the Silverlight Business Application template.

Image 1

In the ASP.NET project, I added an Entity Framework Model.

Image 2

Image 3

In this demo, I'm using the AdventureWorksLT database.

Image 4

Image 5

These are the entities we will use in this demo:

Image 6

Build the project and add a Domain Service Class:

Image 7

Here are all the entities selected to be added to the domain service:

Image 8

Now we can add a new Report. In this case, we are using Reporting Services in Local mode.

Image 9

In the report, when a Tablix component is added, a dataset is requested. In this case, the Choose the Dataset Wizard sees the domain context that we added before.

Image 10

For this demo, I created a new class that I will use to bind to the report. There are cases in which that is preferable to do because we may need to do some extra processing before the data can be bound to the report:

C#
using System;
using System.Collections.Generic;

using System.Linq;
using System.Web;

using System.ComponentModel.DataAnnotations;


namespace ReportingServicesDemo.Web
{
    public class Orders
    {
        public Orders()
        { }

        [Key]
        public int OrderDetailsID
        {
            get;
            set;
        }

        public int OrderID
        {
            get;
            set;
        }

        public string Product
        {
            get;
            set;
        }

        public int Quantity
        {
            get;
            set;
        }

        public decimal UnitPrice
        {
            get;
            set;
        }

        public decimal UnitPriceDiscount
        {
            get;
            set;
        }

        public decimal LineTotal
        {
            get;
            set;
        }
    }
}

In this class, I made a reference to the System.ComponentModel.DataAnnotations namespace that allows me to add a Key attributte to the OrderDetailsID property - that is a requirement for the class so the domain service can recognize it as an entity.

If we dive into the domain service code, we find this:

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Linq;
using System.ServiceModel.DomainServices.EntityFramework;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;


//// Implements application logic using the AdventureWorksLT2008Entities context.
//// TODO: Add your application logic to these methods or in additional methods.
//// TODO: Wire up authentication (Windows/ASP.NET Forms)
///        and uncomment the following to disable anonymous access
//// Also consider adding roles to restrict access as appropriate.
// [RequiresAuthentication]
[EnableClientAccess()]
public class ADWLTDomainService : 
       LinqToEntitiesDomainService<AdventureWorksLT2008Entities>
{

Now I create a domain operation that exposes the Orders entity I just created in my custom class:

C#
public IQueryable<Orders> GetOrderDetails(int OrderID)
{
    AdventureWorksLT2008Entities adw = new AdventureWorksLT2008Entities();

    var query = from c in adw.SalesOrderDetail.Include("Product")
                where 
                c.SalesOrderID == OrderID
                select new Orders { OrderID = OrderID, 
                OrderDetailsID = c.SalesOrderDetailID, Product = c.Product.Name, 
                Quantity = c.OrderQty, UnitPrice = 
                c.UnitPrice, UnitPriceDiscount = c.UnitPriceDiscount, 
                LineTotal = c.LineTotal };
   return query;
}

Here are some remarks. In this method, I'm using the Entity Framework context instead of the object context that the domain service declares, and exposing like the other select methods as IQueryable.

If we build the project again, the "Choose the DataSet Wizard" sees our custom method and all the fields exposed by the entity ready for our report.

Image 11

Here is the report design together with the dataset available:

Image 12

Now we add a WebForm to the web project in order to place the report using the ReportViewer control:

Image 13

When we add the ReportViewer control, it creates an ObjectDataSource control.

Image 14

Looking at the ObjectDataSource's properties, we can see the Select property of our custom method.

Image 15

Looking at the SelectParameters collection, we see our custom method parameter.

Image 16

Now in the Silverlight project, we add a DataGrid bound to the Sales Orders entity.

Image 17

Each field in the Sales Order ID column is represented as a button just for this demo in order to pass the content value as a parameter on the click event. The idea is to call a popup window using the HtmlPage object, with HtmlPopup options from the System.Windows.Browser namespace.

C#
HtmlPopupWindowOptions options = new HtmlPopupWindowOptions();
options.Left = 0;
options.Top = 0;
options.Width = 930;
options.Height = 800;
options.Menubar = false;
options.Toolbar = false;
options.Directories = false;
options.Status = false;

Button btn = sender as Button;

int OrderID =int.Parse(btn.Content.ToString());

string address = Application.Current.Host.Source.AbsoluteUri;
int i = address.IndexOf("/ClientBin/", 1);
string url = address.Substring(0, i);
url = url + "/RpDemoWebForm.aspx?OrderID=" + OrderID;

if (true == HtmlPage.IsPopupWindowAllowed)
    HtmlPage.PopupWindow(new Uri(url), "new", options);

We can obtain the current web address were the Silverlight XAP application is running, using the Application.Current.Host.Source.AbsoluteUri property. Later, we can create the URI associated with the ReportViewer's Web Form.

Finally, we can see our Order Details report.

Image 18

Points of Interest

I hope this article can be helpful while we wait for the next Silverlight releases, and also can explore more options in business reporting.

History

  • 07-26-2010: Submitted to CodeProject.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer Sigo S.A.
Venezuela Venezuela
Ernesto Herrera is a Senior Developer, Architect with more than 12 years experience, actually working with Silverlight Line-of-Bussiness Applications, he holds a MCTS Web Application 2.0 Certification, and have a wide experience with sql server since the 6.5 version, on his free time he likes to play tennis with his wife,kids and friends, also enjoy playing Wii with his sons, he works at Sigo S.A., a retail business located at Margarita Island, Venezuela.

Comments and Discussions

 
QuestionPararmeter(OrderID) not being passed Pin
Ibrahim Islam26-Jul-12 1:25
Ibrahim Islam26-Jul-12 1:25 
QuestionHtmlPage.IsPopupWindowAllowed Pin
Sk8tz16-Apr-12 2:14
professionalSk8tz16-Apr-12 2:14 
QuestionHow to manage the authentication/authorization Pin
Member 375780520-Feb-12 22:06
Member 375780520-Feb-12 22:06 
AnswerRe: How to manage the authentication/authorization Pin
JP®17-Apr-12 7:47
JP®17-Apr-12 7:47 
QuestionDomainDataSource not available as data source Pin
Chrysokomas24-Jun-11 0:43
Chrysokomas24-Jun-11 0:43 
AnswerRe: DomainDataSource not available as data source Pin
Ernesto Herrera28-Jun-11 4:16
Ernesto Herrera28-Jun-11 4:16 
GeneralStuck at last step Pin
Vishwanatha J20-Apr-11 18:24
Vishwanatha J20-Apr-11 18:24 
GeneralRe: Stuck at last step Pin
Ernesto Herrera28-Jun-11 4:17
Ernesto Herrera28-Jun-11 4:17 
GeneralThank you so much for sharing Pin
vsnewcomer16-Feb-11 3:30
vsnewcomer16-Feb-11 3:30 
GeneralRe: Thank you so much for sharing Pin
vsnewcomer16-Feb-11 3:42
vsnewcomer16-Feb-11 3:42 
Question[My vote of 1] Code does not run Pin
louiso9910-Dec-10 7:02
louiso9910-Dec-10 7:02 
AnswerRe: [My vote of 1] Code does not run Pin
Ernesto Herrera16-Dec-10 10:52
Ernesto Herrera16-Dec-10 10:52 
GeneralIntegrate Reporting Services Pin
technette23-Sep-10 9:29
technette23-Sep-10 9:29 
GeneralRe: Integrate Reporting Services Pin
Ernesto Herrera28-Jun-11 4:19
Ernesto Herrera28-Jun-11 4:19 
GeneralExcelente articulo Pin
jsoques20-Sep-10 16:54
jsoques20-Sep-10 16:54 
GeneralRe: Excelente articulo Pin
Ernesto Herrera28-Jun-11 4:20
Ernesto Herrera28-Jun-11 4:20 
GeneralMy vote of 5 Pin
Abhinav S7-Aug-10 18:19
Abhinav S7-Aug-10 18:19 
GeneralRe: My vote of 5 Pin
Ernesto Herrera19-Aug-10 6:17
Ernesto Herrera19-Aug-10 6:17 
GeneralGood work Pin
Abhishek Sur31-Jul-10 11:02
professionalAbhishek Sur31-Jul-10 11:02 
GeneralRe: Good work Pin
Ernesto Herrera2-Aug-10 4:14
Ernesto Herrera2-Aug-10 4:14 
GeneralExcellent Pin
goodnamecool31-Jul-10 6:19
goodnamecool31-Jul-10 6:19 
Excellent Thumbs Up | :thumbsup: !!!....Hold on Bolivar!.. Laugh | :laugh:
GeneralRe: Excellent Pin
Ernesto Herrera28-Jun-11 4:21
Ernesto Herrera28-Jun-11 4:21 
GeneralGOOD Pin
Sachy28-Jul-10 5:25
Sachy28-Jul-10 5:25 
GeneralRe: GOOD Pin
Ernesto Herrera28-Jul-10 5:36
Ernesto Herrera28-Jul-10 5:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.