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.