HomeASP.NET Binding Data to the ReportViewer Control D...
Binding Data to the ReportViewer Control Dynamically in ASP.NET 2.0
This is the second article in a series focusing on designing and presenting native reports using ASP.NET 2.0. Throughout this series, I will focus on working with the “ReportViewer” control in local mode to develop web-based applications.
If you are new to working with the ReportViewer control, I strongly suggest you go through my first article in this series. That article really gives you a step-by-step approach to working with the ReportViewer control.
The entire source code for this article is available in the form of a downloadable zip file. The solution was developed using Microsoft Visual Studio 2005 Professional Edition on Microsoft Windows Server 2003 Enterprise Edition together with Microsoft SQL Server 2005 Developer Edition. I didn’t really test the solution with any other or previous editions.
Binding a SELECT statement to a ReportViewer control in ASP.NET 2.0: design
I discussed several types of reporting strategies to implement in ASP.NET 2.0 applications in my first article. I also gave a step-by-step approach to working with the ReportViewer control in the same article. So I will not be repeating any of that material here.
In my previous article, I developed reports by directly connecting to database tables/views. That scenario won't be helpful every time. Let us imagine that I would like to develop a report based on a dynamic SELECT statement. This is a little bit tricky when compared to the approach I discussed in my previous article.
First of all, we need to keep in mind that any “table” in a report (at local mode) must adhere to a structure. This structure will generally be a “strongly-typed-dataset.” Without creating a strongly-typed-dataset, it is very difficult to design a report. Creating a strongly-typed-dataset was covered in my previous article.
Even now, to bind a report to a SELECT statement, we need to create a strongly-typed-dataset which contains exactly the same columns we retrieve using the SELECT statement. In other words, we will make filters, joins, sorting etc. dynamic, but not the structure (or set of columns). The structure (or set of columns) must always remain the same when designing or developing reports.
For this scenario, I created a strongly-typed-dataset (called SalesData.xsd) as follows.
It is simply a data table (dragged from the toolbox) with user specific columns. It has no relation to any database, and no tableadapters are created.
I added a new report (called SampleReport.rdlc) to the project and attached it to the dataset as follows:
Once you have created the datasets and reports as given in the previous section, we need to work with the ReportViewer control to render the data based on the dynamic SELECT.
Drag a ReportViewer control onto the default.aspx and modify your code-behind file in such a way that it looks something like the following:
ImportsMicrosoft.Reporting.WebForms
ImportsSystem.Data
ImportsSystem.Data.Sqlclient
PartialClass _Default
Inherits System.Web.UI.Page
ProtectedSub Page_Load(ByVal sender AsObject, ByVal e As System.EventArgs) HandlesMe.Load
'Set the processing mode for the ReportViewer to Local
In previous sections, I demonstrated how to work with a simple SELECT statement and bind it to the ReportViewer control. Now, I shall demonstrate how to bind an XML document to the ReportViewer control.
Before binding, we need to add an XML document to our project (called SalesDataFile.xml) with a structure that exactly matches that of the dataset created in the previous sections. It is also recommended that we have the schema reference the same dataset.
The following is the simple XML document I created for the purpose of this demonstration.
From the above document you can observe that the root element will be nothing but the dataset name. Each row gets stored in the form of “Data” (or data table within the dataset). And every row is framed with the columns exactly matching the dataset we created earlier.
Source Code
Add a new web form (called XMLbasedReport) and drag a ReportViewer control onto it. Modify your code-behind file in such a way that it looks something like the following:
ImportsMicrosoft.Reporting.WebForms
ImportsSystem.Data
PartialClass XMLbasedReport
Inherits System.Web.UI.Page
ProtectedSub Page_Load(ByVal sender AsObject, ByVal e As System.EventArgs) HandlesMe.Load
'Set the processing mode for the ReportViewer to Local
In general, every project contains several classes to deal with business logic. Sometimes I may need reports based on the logic/data given through business logic classes. I try to cover this scenario in this section.
Let us now develop some simple business logic to retrieve information from a text file and provide itself as a data source (or report data source) to the ReportViewer control. The following is the class (SalesInfo.vb), which imitates the columns of the dataset created earlier:
ImportsMicrosoft.VisualBasic
PublicClass SalesInfo
Dim _SalesPersonID AsString
Dim _FirstName AsString
Dim _SalesQuota AsString
Dim _SalesYTD AsString
Dim _SalesLastYear AsString
PublicProperty SalesPersonID() AsString
Get
Return _SalesPersonID
EndGet
Set(ByVal value AsString)
_SalesPersonID = value
EndSet
EndProperty
PublicProperty FirstName() AsString
Get
Return _FirstName
EndGet
Set(ByVal value AsString)
_FirstName = value
EndSet
EndProperty
PublicProperty SalesQuota() AsString
Get
Return _SalesQuota
EndGet
Set(ByVal value AsString)
_SalesQuota = value
EndSet
EndProperty
PublicProperty SalesYTD() AsString
Get
Return _SalesYTD
EndGet
Set(ByVal value AsString)
_SalesYTD = value
EndSet
EndProperty
PublicProperty SalesLastYear() AsString
Get
Return _SalesLastYear
EndGet
Set(ByVal value AsString)
_SalesLastYear = value
EndSet
EndProperty
EndClass
The above class simply contains all the properties which get logically mapped to the dataset columns. Now we need to create another class, which can expose several objects based on the above class. The next section will deal with this issue.
This is an extension from the previous section. Add one more class (Sales.vb), which is mainly used to expose the objects based on the above class. The code should look like the following:
ImportsMicrosoft.VisualBasic
ImportsSystem.Data
ImportsSystem.Collections.Generic
PublicClass Sales
PublicFunction ListSales() As ArrayList
Dim Sales AsNew ArrayList
Dim fileName AsString = HttpContext.Current.Request.MapPath("SalesData.csv")
Using parser AsNew FileIO.TextFieldParser(fileName)
parser.Delimiters = NewString() {","}
parser.HasFieldsEnclosedInQuotes = False
Dim fields AsString()
fields = parser.ReadFields()
DoWhile fields IsNotNothing
Dim info AsNew SalesInfo
With info
.SalesPersonID = fields(0)
.FirstName = fields(1)
.SalesQuota = fields(2)
.SalesYTD = fields(3)
.SalesLastYear = fields(4)
EndWith
Sales.Add(info)
fields = parser.ReadFields()
Loop
EndUsing
Return Sales
EndFunction
EndClass
Now, add a new web form (ObjectBasedReport.aspx), drag a ReportViewer control and finally set “SampleReport.rdlc” at the “Choose Report” option in the Smart Tag.
That automatically adds an “ObjectDataSource” control to your designer.
Using the “ObjectDataSource,” open the smart tag menu and choose “Configure Data Source.”
You will be provided with a wizard. Provide “Sales” as your “business object” and click "Next."
In the next screen, for the SELECT tab, choose “ListSales(), returns ArrayList” as the method.
For all the rest of the tabs, you can select “none.” Finally click “Finish.” When you execute, your reports get bound to the customized business logic object source!
Any feedback, problems, suggestions, bugs, errors, improvements etc., are highly appreciated at http://jagchat.spaces.live.com.