AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=776&pId=-1
Creating Dynamic DataSets for Crystal Reports in ASP.NET 2.0
page
by Chuck Bradley
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 56104/ 46

Introduction

[Download Sample]

This article describes how to use the CrystalReportsViewer and Crystal Report Template components within VS 2005 and populate a report from a dynamically generated DataSet at runtime without login errors. This is typically known as the "push" method.

 

The Environment

Crystal Reports Engine: Version 10.2.3600.0

Visual Studio 2005: Version 8.0.50727.42

MS FrameWork Version 2.0.50727

Desktop OS: Windows XP Pro SP 2

Desktop Hardware: Intel Xeon™ CPU 3.00GHz, 1.00 GB RAM

Language: C#

 

The Need

I want to allow the client to bring up a web page in a browser, create a DataSet from information on the page or passed in, hook the DataSet into a Crystal Report and view the report within a CrystalReportsViewer component on the page, avoid login errors, and not rely on an XML file being sustained on the server.  The data for the report needs to be generated dynamically, without having to hit a back-end database for the content, and must come from a DataSet created on the fly to populate a Crystal Report to be printed.

 

The Problem

Creating the DataSet on the fly is straightforward. The idea was to be able to push it into a report within a stateless environment. The issue was that when I tried to load the DataSet object into the report, I kept getting errors in the display of the CrystalReportsViewer.

 

The Effort

I had tried to hook the Crystal Report Template to a class that would provide a DataSet or a list object that implemented IEnumerable such as a collection or an array from a public property.  The DataBase Expert in the right-click context menu on the Crystal Report Template had no problem finding the class as a Project Data|.NET Object and seemed to bind to the public properties and treat them as fields for the report, which is really cool.

I also tried letting the Viewer add a CrystalReportSource from the ReportSource property and configure the CrystalReportSource to look at the class. At runtime I got various errors depending upon the configuration I was trying.

In the course of these exercises some of the errors were:

Error in File C:\DOCUME~1\MyMachine\ASPNET\LOCALS~1\Temp\PreviewReport {6C87A56E-1E2D-40BE-9FBD-24409A81019F}.rpt: Unable to connect: incorrect log on parameters

Logon failed. Details: crdb_adoplus : Object reference not set to an instance of an object. Error in File C:\DOCUME~1\ MyMachine\ASPNET\LOCALS~1\Temp\CrystalReport {7DEF4E8F-DCD1-414A-9242-D51EFBF4A2FF}.rpt: Unable to connect: incorrect log on parameters

I tried resetting permissions on the application folder as well as the AppCode folder where VS 2005 likes to put classes, but was not successful at getting rid of the error.  During all of this I referred to the articles /crystal/redir.aspx?ArticleURL=/532 by Richard Dudley as well as /crystal/redir.aspx?ArticleURL=/490 by Eric Landes.

At this point I'm wondering if my DataSet is getting populated the way it should and whether or not an XML schema file is needed for one of the Crystal components.  I made the DataSet create an XML image file by running the app with the WriteXML method.  I set the Crystal Report Template to look at the XML file in DataBase Expert.  When it ran, I got an error of: "You are not authorized to view this page." The page wasn’t showing the CrystalReportsViewer at all, as I was in an error page of course.

I eventually decided to use a ReportSource from code rather from the toolbar in design view. I found that during configuration changes in design view, VS 2005 would sometimes gracefully ask to shut down; other times it would bail clean off of the desktop by itself.

I deleted the CrystalReportSource from design view, added code to create a ReportDocument object, and pointed it to the Crystal Report Template using the Load method.  It ran fine and was then displaying the static data that was in the XML image file I had made earlier off of the DataSet. If static data is what you need, then that’s OK, but I needed to be able to have dynamic data fill the DataSet at runtime of the page.

By setting the ReportDocument.DataSource property to the DataSet, I was able to get the data from the page rather than the static XML file.

 

My Solution

The reason I say my solution is that there may be much better ways to do this, I'm sure. This one just happened to work for me, and I know what I went though to find it and need to share possibly useful information.

Before adding any Crystal components in design view, add code to create an XML file from the DataSet you wish to use for the source of the report; in the constructor of the DataTable, give it a meaningful name to refer to when you are in the Crystal Report wizard and then run your application as below.

 

DataSet myDS = new DataSet();
DataTable dtMyTable = new DataTable("preview");
 
DataColumn myCol0 = new DataColumn("facility");
myCol0.DataType = System.Type.GetType("System.String");
myCol0.MaxLength = 256;
myCol0.AllowDBNull = true;
 
DataColumn myCol1 = new DataColumn("doctype");
myCol1.DataType = System.Type.GetType("System.String");
myCol1.MaxLength = 256;
myCol1.AllowDBNull = true;
 
dtMyTable.Columns.Add(myCol0);
dtMyTable.Columns.Add(myCol1);
dtMyTable.AcceptChanges();
 
DataRow myNewRow = dtMyTable.NewRow();
myNewRow["facility"= "MyFacility Works Great!";
myNewRow["doctype"= "MyDocType Field Does Too!";
dtMyTable.Rows.Add(myNewRow);
dtMyTable.AcceptChanges();
 
myDS.Tables.Add(dtMyTable);
 
myDS.WriteXml(@"C:\Inetpub\wwwroot\CrystalTest\tryXML.xml");

 

You may get an error like this when the DataSet tries to write the XML file to the web folder.

 

If you get this, then you need to reset the security on the folder you're trying to write the XML file to. I won't go into the detail of resetting the permissions for two reasons, one being it is not the focus of this article, and second, I am not that good at it and would not want to steer you wrong.  However, I will say this: if you try to set the security by right-clicking the folder to get the context menu that has the tab for Security under the "Sharing and Security…" menu item and the Security tab is not there, bring up Windows Explorer, select MyComputer, then in the menu, click  Tools|Folder Options|View, and unselect the checkbox for "Use simple file sharing (Recommended)". This will add the tab to the right-click context menu for folders.

 

I have also seen an error message of "You are not authorized to view this page" when trying to run a project, particularly if it is code that you have imported, but not yet created an application for in IIS. That being the case, try going to IIS and the properties dialog of the app's folder and click on "Create" to tell IIS to create an application for it.

 

Now back to code; drop a CrystalReportsViewer component onto your .aspx web page from the ToolBar. Leave the Choose Report Source set to <None> and be sure to uncheck the property for Enable Database Logon Prompting.

 

 

As an aside, I must give kudos for VS 2005's ability to retain the formatting on an aspx page when in Source view.  In VS2003, having the IDE reformat your source code when going to and from Design view was frustrating to say the least. I now find myself dragging components straight into the source code from the toolbar and then setting the property I want with IntelliSense and writing cleaner code.

 

Next, add a Crystal Report Template and follow the wizard to format it.

 

Choose the XML file you created in code as the data source for the report. When you navigate to the file, the name you gave the Table in the constructor will show up as a choice.

 

You can then choose which fields are required for your report.

 

The fields will then be placed into the Details section of the report for you.

 

Going back to the code-behind for the page, add code to create a new ReportDocument into which you will load the Crystal Report Template, and set this document's DataSource to the DataSet that the XML file was created from.  Then set the ReportDocument to be the report source for the CrystalReportViewer, and add code to bind it, as follows.

 

CrystalDecisions.CrystalReports.Engine.ReportDocument myReportDocument;
myReportDocument = new CrystalDecisions.CrystalReports.Engine.ReportDocument();
 
myReportDocument.Load(@"C:\Inetpub\wwwroot\CrystalTest\CrystalReport.rpt");
CrystalReportViewer1.ReportSource = myReportDocument;
CrystalReportViewer1.DataBind();
CrystalReportViewer1.DisplayToolbar = false;

 

At this point, you should be able to run the app and display the XML file in the CrystalReportViewer. However, the data you are seeing is coming from the static XML file on the server.  This is good, but not what I needed. What I needed was to be able to populate the report dynamically and not have a dependency on an XML file or have to read or write to one at runtime. Since the report template has already been bolted to the data fields in the XML file, all that is needed is to update the DataSource on the ReportDocument, and then the DataSet will map to the fields in the Template.

CrystalDecisions.CrystalReports.Engine.ReportDocument myReportDocument;
myReportDocument = new CrystalDecisions.CrystalReports.Engine.ReportDocument();
 
//either of these methods should work to get the DataSet into the ReportDocument
//myReportDocument.Database.Tables["preview].SetDataSource(myDS);
//myReportDocument.Database.Tables[0].SetDataSource(myDS);
myReportDocument.SetDataSource(myDS);
 
CrystalReportViewer1.ReportSource = myReportDocument;
CrystalReportViewer1.DataBind();
CrystalReportViewer1.DisplayToolbar = false;

 

Any of these three methods will work for setting the DataSource for the ReportDocument, depending upon what you need to do. It lends itself to a lot of flexibility if you're using multiple tables or data on a complex page.

As a kicker, try deleting the XML file you created for the image to provide to the Crystal Report Template and notice that the app still runs fine. The data is coming from the DataSet, and the XML file is not needed. But note that the Template is mapped to the schema for this XML file, and if you want to change the Template, you will have to re-create the XML file.

 

Summary

These are a few tips to creating Crystal Reports and populating them on the fly from a DataSet. This article is by no means an exhaustive look at the capabilities or a behind-the-scenes view into these components, but just a primer to save time in getting a report up and running and an exposure to the "push" method. I hope this helps.

 


Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-19 1:28:43 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search