Skip to main content

Weblog Ton Stegeman [MVP]

Go Search
Home
  

ODC 2008
If you have a question or suggestion, please contact me through Windows Live Messenger.
My status: .

If I am not online, please send me an e-mail.
Weblog Ton Stegeman [MVP] > Posts > SharePoint 2007 and Reporting Services
SharePoint 2007 and Reporting Services

In one of the projects we are working on, we created a number of Reporting Services and integrated them in SharePoint 2007. This report displays SharePoint data in a printable, exportable report on a SharePoint page. We started of with using a report deployed to our Reporting Services server. In this proof of concept stage, we looked at using the Enesys RS Data Extension. A pretty clever datasource for SharePoint. It did not exactly meet our requirements, so we had to look at another solution. One of my colleagues pointed me to the ReportViewer controls in Visual Studio. This includes an ASP.NET control that is able to display reports in a web page. In this article I will describe how I created a web part that displays an aggregation of SharePoint tasks in a report. For the end user the report looks like this:

image

The user has a dropdown box in the web part that left him/her select a task status. After clicking the button, the reporting web part queries the site collection for all Task list items with that status and puts them in the report.

A big pro that we got by using this control is that we now bypass the Report Server. The report itself is deployed as a resource in the assembly. Therefore we do not need to deploy the report and its permissions. And we bypass the double hop. Nice. By using our Reporting Services server, we would go from SharePoint to the Report Server to get the report. The report server would need to connect back to the SharePoint server to get the data. By using the ReportViewer, we bypass this, because everything happens on the server. As you can see from the screenshot above, this article is not about my skills to build a nice report. I just want to show you how to display a report in SharePoint that is using SharePoint data. At the end of this post you will find a link to a ZIP file containing all sources used in this article.

Step 1 – Setup

In this article I am using Visual Studio 2008, the .NET Framework 3.5 SP1 (this also needs to be available on the SharePoint servers). After creating a new Visual Studio project, (Class library) I targeted the .NET framework to 3.5. Next thing to do is add a reference to the reporting assembly. This control is available in the dll Microsoft.ReportViewer.WebForms.dll, that can be found in folder ‘C:\Program Files\Microsoft Visual Studio 9.0\ReportViewer’. Your solution installer also needs to make the assembly available on the SharePoint server(s). The the reportview is not yet available on the SharePoint servers, you need to deploy these assemblies:

  • Microsoft.ReportViewer.WebForms.dll
  • Microsoft.ReportViewer.Common.dll
  • Microsoft.ReportViewer.ProcessingObjectModel.dll

In the web.config of your SharePoint web application(s) you will need to make some changes. First thing to do is to register the HttpHandler. Add this snippet in the HttpHandlers section:

   1: <add verb="*" 
   2:      path="Reserved.ReportViewerWebControl.axd" 
   3:      type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

In the appSettings section, you need to remove this element:

   1: <add key="ReportViewerMessages" 
   2:      value="Microsoft.SharePoint.Portal.Analytics.UI.ReportViewerMessages, Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" /> 

If you do not remove the element, your reporting web part will display this error message at runtime: “The type Microsoft.SharePoint.Portal.Analytics.UI.ReportViewerMessages, Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c does not implement IReportViewerMessages or could not be found”.
Now your Visual Studio project and your SharePoint are ready to get started.

Step 2 – Create the business objects

The report will use an ObjectDataSource as the datasource. In this step we will create the businessobjects to be used as the datasource. Visual Studio can help you pretty good if you want to connect to SQL Server to get the data for your report. Unfortunately, Visual Studio does not know about SharePoint, and therefore you will have to do the coding around the datasource yourself. First object to create is the Task object. This object is very simple:

   1: public class Task
   2: {
   3:     public Task()
   4:     {
   5:     }
   6:  
   7:     public String Title { get; set; }
   8:     public String Status { get; set; }
   9:     public String Priority { get; set; }
  10:     public String AssignedTo { get; set; }
  11:     public DateTime DueDate { get; set; }
  12:  
  13:     public int DueDays
  14:     {
  15:         get
  16:         {
  17:             return DueDate.Subtract(DateTime.Now).Days;
  18:         }
  19:     }
  20: }

The TaskList object is an object that holds a number of Task objects and is the object that will be used as ObjectDataSource. Therefore this class is decorated with the DataObjectAttribute attribute (from the System.ComponentModel namespace). This class has a parameterless constructor and a public method that returns a List populated with Task items.

   1: [DataObjectAttribute(true)] 
   2: public class TaskList
   3: {
   4:     public TaskList()
   5:     {
   6:     }
   7:  
   8:     [DataObjectMethod(DataObjectMethodType.Select)]
   9:     public List<Task> LoadByStatus(String status)
  10:     {
  11:         List<Task> taskList = new List<Task>();
  12:         SPSiteDataQuery taskQuery = new SPSiteDataQuery();
  13:         taskQuery.Lists = "<Lists ServerTemplate=\"107\" />";
  14:         taskQuery.RowLimit = 10000;
  15:         String query = String.Format(@"<Where><Eq><FieldRef Name='Status' /><Value Type='Text'>{0}</Value></Eq></Where>", status);
  16:         taskQuery.Query = query;
  17:         taskQuery.ViewFields = "<FieldRef Name=\"Title\" /><FieldRef Name=\"AssignedTo\" /><FieldRef Name=\"Priority\" /><FieldRef Name=\"DueDate\" Type=\"DateTime\"/>";
  18:         taskQuery.Webs = "<Webs Scope=\"SiteCollection\" />"; ;
  19:         DataTable projectsTable = SPContext.Current.Web.GetSiteData(taskQuery);
  20:         foreach (DataRow row in projectsTable.Rows)
  21:         {
  22:             Task task = new Task();
  23:             task.Title = GetFieldValue(row, "Title");
  24:             task.Priority = GetFieldValue(row, "Priority");
  25:             task.AssignedTo = GetFieldValueUser(row, "AssignedTo");
  26:             task.DueDate = GetFieldValueDateTime(row, "DueDate");
  27:             taskList.Add(task);
  28:         }
  29:         return taskList;
  30:     }
  31: }

The function that is called by the ObjectDataSource is LoadByStatus. This takes a status string as a parameter and returns a List of Task items. The class also contains a number of helper methods to get the data from the DataTable. They are irrelevant for this blog post, but they can be found in the source code that you will find in the ZIP file at the bottom of this article.

Step 3 – Create the report

Now that we have our business objects ready, we can create the report. In your Visual Studio project, click “Add new item” and select the “Report” from the Reporting page:

image

Select the rdlc file you just added in the Solution Explorer and set the Build Action to Embedded Resource.

image

In the Datasources windows, click the Add New Data Source button:

image

In the next dialog, select Object as the Data Source Type:

image

The next step in the wizard asks you to which object you with to bind. Select the Task object, because that is the object we want to use in our report:

image

In the Report menu of Visual Studio, select Data Sources.

image

In the dialog select the datasource object you just added, and click Add to report.

image

Add a table to the report and drag one of the fields to the detail row:

image

From this point on, it is business as usual (if you are used to building reports in Reporting Services).

Step 4 – Create the reporting web part

Last thing to do it to create a new web part that will render the report. The snippet below shows the part of the CreateChildControls method of the task reporting web part that created the objects we need. Full code (that also creates the dropdownlist and the button) can be found in the ZIP file at the bottom of this post.

   1: _reportViewer = new ReportViewer();
   2: _reportViewer.Width = new Unit(100, UnitType.Percentage);
   3: _reportViewer.Height = new Unit(100, UnitType.Percentage);
   4: _reportViewer.Visible = false;
   5: _reportViewer.LocalReport.ReportEmbeddedResource = "TST.SharePoint2007.Reporting.TaskReport.rdlc";
   6: Controls.Add(_reportViewer);
   7:  
   8: _datasourceTaken = new ObjectDataSource();
   9: _datasourceTaken.ID = "datasourceTasks";
  10: _datasourceTaken.SelectMethod = "LoadByStatus";
  11: _datasourceTaken.SelectParameters.Add(new Parameter("status", System.Data.DbType.String));
  12: _datasourceTaken.TypeName = "TST.SharePoint2007.Reporting.TaskList, TST.SharePoint2007.Reporting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=503edd7b21a430b3";
  13: _datasourceTaken.Selecting += new ObjectDataSourceSelectingEventHandler(datasourceTasks_Selecting);
  14: Controls.Add(_datasourceTaken);

After creating the ReportView control, the reference to the report file needs to be set. Our report is an embedded resource in the assembly. Therefore we seet the ReportEmbeddedResource property of the LocalReport (in line 5). The full name to load the report is the name of the assembly (TST.SharePoint2007.Reporting) followed by the name of the report (TaskReport.rdlc).

After creating the viewer control, the ObjectDataSource is created. The TypeName property in line 12 is the reference to the business object we created in step 2. The SelectMethod and SelectParameters need to match a public function decorated with the DataObjectMethod attribute in that classe. In my case that is the function LoadByStatus, which has a parameter called status of type String (see step 2). The snippet below shows the implementation of the Selecting event.

   1: private void datasourceTasks_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
   2: {
   3:     e.InputParameters["status"] = _getStatus.SelectedValue;
   4: }

In this event we get the value of the status dropdownlist (see the first screenshot) and pass the value to the inputparameter of the datasource. Last thing to do it to implement the event handler for the button. When a user clicks the “Generate Report” button, this method is called:

   1: private void search_Click(object sender, EventArgs e)
   2: {
   3:     ReportDataSource dataSource = new ReportDataSource("TST_SharePoint2007_Reporting_Task", _datasourceTaken);
   4:     _reportViewer.LocalReport.DataSources.Clear();
   5:     _reportViewer.LocalReport.DataSources.Add(dataSource);
   6:     _reportViewer.Visible = true;
   7:     _reportViewer.LocalReport.Refresh();
   8: }
   9:  

In this method, a new ReportDataSource object is instantiated and added to the report. Please note that the first parameter of the constructor, the name parameter, needs to match the name of the datasource in the report. This is the name of the data source you selected in step 3 in the Report Data Sources dialog:

image

The second parameter of the ReportDataSource constructor is a reference to the ObjectDataSource we created in CreateChildControls.

After building and deploying your web part, you should now be able to run the report.

Conclusion

The .NET ReportViewer control is a powerful control to use if you need to do reporting on SharePoint data in SharePoint. It saves you from managing a report server. You don’t need to deploy the report, because it it part of the assembly and you do not have to worry about the double hop issue. Another option would be to run Reporting Services in integrated mode with SharePoint. In our case, that was not an option. We had very specific requirements for the data retrieval process and therefore we moved in this direction.

Full source code for this sample can be found in this ZIP file.

Comments

There are no comments yet for this post.
Items on this list require content approval. Your submission will not appear in public views until approved by someone with proper rights. More information on content approval.

Title


Body *


Your city *


Type the name of the city you live in (making it easier to handle spam...)

CurrentDate *

Select the current date (see if this gives me fewer spam...)
Attachments

 Links

  SharePoint Object on CodePlex
  Screencast introducing SharePoint Objects
  Content by Type and Filter Web Parts on CodePlex
  Archive
  Archive (Calendar)

 My Latest Blog Posts

Scripting SharePoint 2007 setup: choices and conceptsUse SHIFT+ENTER to open the menu (new window).
Adventures in Visual Studio 2010: Migrate the Content By Type web part to SharePoint 2010Use SHIFT+ENTER to open the menu (new window).
Register SharePoint themes by using a featureUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010 development on Windows 2008 Server R2 – Getting StartedUse SHIFT+ENTER to open the menu (new window).
New release SharePoint Objects: features and groupsUse SHIFT+ENTER to open the menu (new window).
Constructing the url to the SharePoint Edit Permissions pageUse SHIFT+ENTER to open the menu (new window).
Screencast: introduction to SharePoint ObjectsUse SHIFT+ENTER to open the menu (new window).
SharePoint 2007 and Reporting ServicesUse SHIFT+ENTER to open the menu (new window).
SharePoint Objects – Insight in usage of your SharePoint artifactsUse SHIFT+ENTER to open the menu (new window).
SharePoint 2007 Custom list schema and the Content Query Web PartUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010 Silverlight Client Object Model – ExecuteQuery vs ExecuteQueryAsyncUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010, the Client Object Models and Bing MapsUse SHIFT+ENTER to open the menu (new window).
Having fun with SharePoint 2010, Silverlight 3 and Bing MapsUse SHIFT+ENTER to open the menu (new window).
Connecting TFS 2010 projects to SharePoint sitesUse SHIFT+ENTER to open the menu (new window).
Adding a database to the SharePoint database Server using SPDatabaseUse SHIFT+ENTER to open the menu (new window).