Previously, we introduced a series of posts that would show the interesting parts of a (very basic) feedback service implementation. This is part VI, here are the other bits:
Creating the report
Good news is we're almost finished. We've created our client feedback mechanism and built a service to receive and push the data into a SQL 2005 database. We can even access the screenshots we stored in the database
too. Now we need the main piece - the ability to see the feedback data and create links to our ViewPng.ashx image viewer.
And for this we're going to use SQL 2005 Reporting Services. Except we're not. We're going to use the ASP.NET Report Viewer and Reporting Services' 'Report Definition Language' (RDL) to create our report. But there'll be no sign of a reporting services server anywhere
. My hosting company don't have one for me to use.
Of course, I could just go and create a report using a GridView in ASP.NET and build in lots of pagination and sorting. But why would I do this when I have access to a free
reporting engine that contains all this stuff and can even export to PDF and therefore supports great printing
Let's get started then. First, we need to add another method to our FeedbackDal to get all the data (yes, this might not be the most scalable of ideas but we're just getting started and we can optimise later once I've got you interested in the Report Viewer :) ).
And here's that extra Dal function (note we don't waste any time getting the screengrab data).
public static List<Feedback> GetAllFeedback()
Database db = DatabaseFactory.CreateDatabase("FeedbackService");
DbCommand cmd = db.GetSqlStringCommand(@"SELECT * FROM Feedback");
using (IDataReader reader = db.ExecuteReader(cmd))
List<Feedback> listFeedback = new List<Feedback>();
Feedback feedback = new Feedback();
feedback.Comments = reader["Comments"].ToString();
feedback.EmailAddress = reader["EmailAddress"].ToString();
feedback.FeedbackType = (FeedbackType)Enum.Parse(typeof(FeedbackType), reader["FeedbackType"].ToString());
feedback.UserName = reader["UserName"].ToString();
feedback.Id = (int) reader["FeedbackId"];
Next, we'll need a new .aspx page and why not create a folder called Admin inside the same web application we used to host our WCF service? Let's make this our default page inside this folder. We should put our ViewPng.ashx in here too:
On the design surface of our new page (default.aspx) we need to drag a Report Viewer control from the toolbox. Don't forget to set both the Height and the Width of the ReportViewer control to 100%.
Using the task function at the top right of the Report Viewer control (in the design view) choose the Design New Report link.
This will create a new report called Report.rdlc. Now we can start designing our report, but first we need a data source. Since we've already created the appropriate method, we just need to find it in the Website Data Sources window.
Note: if you can't see your type in the Website Data Sources it's probably because you, very sensibly, made the Dal a static type. For some reason the Website Data Sources window doesn't see classes that don't have a default public constructor (but static methods are fine). Best go make your class non-static then. :|
Next, from the toolbox add a Table to your report. Now you can start dragging fields into the report table like so...
Note how the column headings are automatically created for you too. You can also format the text, why not embolden the column headings to make them look more heading-like.
So far, our report has just three columns: UserName, Email Address and Comments. We're going to add another one to contain a link to the screengrab. Add another column by rigth clicking on the gray slab above the last column's header, and choose 'Insert Column to the Right'.
This final column isn't going to contain data, instead it will contain a link that always reads "View Screenshot". And it's as easy as clicking in the details row and typing ="View Screenshot"
. Whilst we're here, we should format the text to look like a link by making it blue and underlined.
To make this text a link, we must setup the Navigation Properties. Right click on the cell and choose properties. Then choose the Navigation tab and set the Hyperlink action to 'Jump to Url'. We can enter a VB expression here which makes use of the data: ="http://feedback.example.com/Admin/ViewPng.ashx?id=" & Fields!Id.Value
. Note that we have to specify an absolute url or the link won't work.
Now back to our ReportViewer control on the default.aspx page. Use the Report Viewer's quick task pane and choose your report in the dropdown.
This will automatically create an ObjectDataSource on the page for you, because the ReportViewer control is nice like that. We now need to make sure that our report viewer allows links to external pages. Fortunately this is easy when you know where to look. Just select the Report Viewer control and head off to the Properties window in Visual Studio. Expand the LocalReport
property and set EnableHyperlinks to true.
You may also want to set the HyperlinkTarget property to '_blank' (a property of the ReportViewer, not the LocalReport) if you'd like the links to open in a new window.
And we're done.
Now we just have to run the report. I've added a nice big textbox at the top to spruce things up a bit :)
Now we've literally scuffed the surface of what the ReportViewer and client reporting can do here, but hopefully you've seen that it offers a very easy draggy-droppy way to create a report in ASP.NET without getting your hands dirty in HTML. And it even supports exporting to PDF. Awesome.
PS - Don't forget to secure your Admin folder! I'll leave that as an exercise for the reader for now.