Jan
5
Written by:
Michael Washington
1/5/2014 3:32 PM
Note: You can use the live application at the following link: https://survey.lightswitchhelpwebsite.com/HTMLClient (use your username and password from LightSwitchHelpWebsite.com).
You can embed reports into the pages of your Visual Studio LightSwitch HTML Client applications and allow your end users to print them and export them to PDF, Microsoft Word and Excel.
We start with the application from the article: LightSwitch Survey: Handling Complex Business Logic Using WCF RIA Services.
We click on one of the Survey Results…
We see an embedded Report Viewer Control that displays the report and chart for the selected Survey.
Users can export the report to various formats for printing.
The reports can be interactive providing tooltips for charts.
Creating The Report
We start off with the WCF RIA Service that combines the tables into one collection. Most reports require data from several tables and a WCF RIA Service allows you to easily do this.
Because this is a Visual Studio LightSwitch 2012 application we must switch to File View (you do not need this step with Visual Studio LightSwitch 2013).
We create a Reports folder in the Server project, and we right-click on it and select Add then New Item.
We select Report or the Report Wizard.
Any WCF RIA Services will show up in the Data source drop down, so a WCF RIA Service is easily consumed in the Report designer. Intrinsic LightSwitch tables are not. To consume a LightSwitch table directly in the report designer, see the article: Printing Sql Server Reports (.rdlc) With LightSwitch.
The data source is only for designing the report. We will have to write code to provide data to the report at runtime in a later step.
We complete designing the report.
Include the .rdlc File in the Build
The report is an .rdlc file and it will not be included in the build in a Visual Studio 2012 project if we don’t right-click on the project and select Unload Project…
.. edit the .ls3proj file…
…add an entry for the .rdlc file…
… reload the project…
… and right-click on the project and set it as the StartUp Project.
Make the Report Run Fast
To only pull back the data we need we create a WCF RIA Service that takes a SurveyID so we only pull back the data we need:
public IQueryable<SurveyResult> GetSurveyResultByID(int? SurveyID)
{
var colSurveyResult = from SurveyQuestions in this.Context.SurveyQuestions
where SurveyQuestions.Survey.Id == SurveyID
select new SurveyResult
{
SurveyId = SurveyQuestions.Survey.Id,
QuestionId = SurveyQuestions.Id,
Question = SurveyQuestions.Question,
TotalResponses = SurveyQuestions.SurveyAnswers.Count(),
ChoiceOne = SurveyQuestions.SurveyAnswers.Where(x => x.Choice == 1).Count(),
ChoiceTwo = SurveyQuestions.SurveyAnswers.Where(x => x.Choice == 2).Count(),
ChoiceThree = SurveyQuestions.SurveyAnswers.Where(x => x.Choice == 3).Count(),
ChoiceFour = SurveyQuestions.SurveyAnswers.Where(x => x.Choice == 4).Count(),
ChoiceOneText = SurveyQuestions.Choice1,
ChoiceTwoText = SurveyQuestions.Choice2,
ChoiceThreeText = SurveyQuestions.Choice3,
ChoiceFourText = SurveyQuestions.Choice4
};
return colSurveyResult;
}
We update the data source…
It will show as a sub query that takes a parameter.
Report Viewer Control
We place a Report Viewer control on a .aspx page…
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportViewer.aspx.cs"
Inherits="LightSwitchApplication.Reports.ReportViewer" %>
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>ReportViewer</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana"
Font-Size="8pt" InteractiveDeviceInfos="(Collection)"
WaitMessageFont-Names="Verdana" WaitMessageFont-Size="14pt" Width="590px" Height="590px">
</rsweb:ReportViewer>
</div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
</form>
</body>
</html>
… and use the following code for the code behind that takes a query string parameter for SurveyId and retrieves the results for the selected Survey:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.Reporting.WebForms;
namespace LightSwitchApplication.Reports
{
public partial class ReportViewer : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["SurveyId"] != null)
{
if (!Page.IsPostBack)
{
ShowReportViewer();
}
}
}
#region ShowReportViewer
private void ShowReportViewer()
{
// Load the .rdlc that contains the report
this.ReportViewer1.ProcessingMode = ProcessingMode.Local;
this.ReportViewer1.LocalReport.ReportPath = Server.MapPath("~/Report1.rdlc");
// Get the data for the report
ReportViewer1.LocalReport.DataSources.Add(
new ReportDataSource("DataSet1", LoadData()));
}
#endregion
#region LoadData
private IEnumerable<SurveyResult> LoadData()
{
using (var serverContext = ServerApplicationContext.CreateContext())
{
// SurveyId is passed to the page
int SurveyId = Convert.ToInt32(Request.QueryString["SurveyId"]);
// Get the data from LightSwitch WCF RIA Service
var result = from SurveyResults in serverContext.DataWorkspace.WCF_RIA_ServiceData
.GetSurveyResultByID(SurveyId).Execute()
select SurveyResults;
return result;
};
}
#endregion
}
}
Consume the Report In the LightSwitch HTML Client
To display the report in the LightSwitch HTML Client, we simply use a Custom Control.
We select Edit Render Code for the control and use the following code:
myapp.SurveyResults.ScreenContent_render = function (element, contentItem) {
// Show Loading message
var LoadingDiv = $("<div></div>");
var Loading = $("<h1> Loading Report...</h1>");
Loading.appendTo(LoadingDiv);
LoadingDiv.appendTo($(element));
// Get Report
var HTMLContent = $("<div></div>").html(
"<object width='650px' height='650px' data='../reports/ReportViewer.aspx?SurveyId="
+ contentItem.screen.SurveyId + "'/>"
);
// Make report appear on top of the Loading message
HTMLContent.css({
"margin-top": "-50px"
});
HTMLContent.appendTo($(element));
};
Deployment
You will need to install the Microsoft Report Viewer 2012 Runtime Package on the web server that displays the report.
Links
LightSwitch Survey: Handling Complex Business Logic Using WCF RIA Services
Printing With LightSwitch
Printing Sql Server Reports (.rdlc) With LightSwitch
Note, you can see this site if you have any questions about the Report Viewer Control: http://www.gotreportviewer.com
Download Code
The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx
(you must have Visual Studio 2012 (or higher) installed to run the code)
25 comment(s) so far...
Hi Michael,
Very nice & beautifull & professional! Just waiting for a powerfull DataGrid (see Winforms-, WPF-, Silverlight-, ms access-grids, ...) and we can start creating real LOB-applications!
Grts,
Daniel Daniel
By LiberIT on
1/7/2014 12:34 AM
|
@LiberIT - Thank you :)
By Michael Washington on
1/7/2014 4:41 AM
|
Hi Michael, Thanks for this really useful article. I want to be able to print from my RDLC reports but the example you have shown does not seem to have the print button enabled. I have tried setting this.ReportViewer1.ShowPrintButton = true; in the ShowReportViewer() function but it does not seem to have any effect. The example you refer to at the top of your article and in the links only seem to work with the Lightswitch desktop client. Have you any ideas on simple ways to accomplish this in the HTML client?
Thanks Charlie
By Charlie on
1/8/2014 4:46 AM
|
@Charlie - I did not make the report control wide enough to show the print button, just make it wider and it should show. Also see: http://stackoverflow.com/questions/20079120/printing-using-reportviewer-in-chrome-and-firefox
By Michael Washington on
1/8/2014 4:49 AM
|
** [NOTE: The Article and the code has been updated to address this issue] **
A good demo on using report viewer in apps where we forgot it was possible. Please can you optimise you query a bit more though! Try this report when you have 10000 or more rows and you'll be scratching you head while you wait for it to run if your data source is any distance from your server. I am so disappointed in the ls community when i see these almost good examples, when people put then into production all we collectively are doing is telling people that ls html client is inherently slow.please change any ls entity linq statements from [tableOrView].GetQuery().Execute().Where... To a query on the data source, otherwise you pull ALL records back on execute when you only want a small subset.i now spend a large percentage of time fixing ls apps with this very problem, but nearly every simple ls example out there has this issue... Please people, lets improve the effectiveness of our community through some production ready examples, lest we run the risk of everyone moving away from ls html client all together
** [NOTE: The Article and the code has been updated to address this issue] **
By Chris Schaller on
2/1/2014 5:23 AM
|
@Chris Schaller - Thank you. I updated the code (see the section "Make the Report Run Fast") to use a query that I confirmed only pulls back the records for the selected Survey ID.
By Michael Washington on
2/1/2014 5:12 AM
|
I was curious if you could provide an example for how to do this in VB. I followed the article all the way up to "Make the Report Run Fast", but was running into some issues with the code conversion. I was also somewhat lost because I am using VS 2013 and I believe in 2013 the reports are included in the build automatically, so I was not sure if I had to unload and add the reporting piece as part of the build. Also when you say "We place a Report Viewer control on a .aspx page…", which aspx page are you referring too? I am a newbie to lightswitch and decent with VS but would it be possible to get some more explanation on this piece as well. Thank you for your contributions to the community.
By Ken Carrier on
2/4/2014 8:34 AM
|
@Ken Carrier - Sorry no VB examples :) To be totally honest, it is a matter of time. I simply throw out code that I am working on and it is always in C#. However, I provide the code that you can download so that should clear up any questions my article may not make clear.
By Michael Washington on
2/4/2014 8:37 AM
|
Michael I am a lot farther today than I was yesterday. I get the message that data is loading but nothing is being returned. In your code this is the line I think it is hanging on. var result = from SurveyResults in serverContext.DataWorkspace.WCF_RIA_ServiceData.GetSurveyResultByID(SurveyId).Execute()select SurveyResults;
In a C# to VB Converter it gives me this, any ideas? It does not seem to like SurveyResults at the end of the statement. Dim result = From SurveyResults In serverContext.DataWorkspace.WCF_RIA_ServiceData.GetSurveyResultByID(SurveyId).Execute()SurveyResults
I will continue googling but that I would ask.
By Ken Carrier on
2/5/2014 1:04 PM
|
@Ken Carrier - Sorry I am no use when it comes to VB and Linq. C# and Linq I know well, but VB and Linq is a syntax I am not good at :(
By Michael Washington on
2/5/2014 2:17 PM
|
@Michael - After some more digging it appears the issue is with the DataObjectContext. My field in the database is a Date field but in the DataObjectContext it is using DateTime so when the report runs it is returning an error about converting DateTime. I have no DateTime fields just Date. Is this an issue with RIA?
By Ken Carrier on
2/6/2014 10:21 AM
|
@Ken Carrier - Date to DateTime conversion should not be a problem. But if you have specific code post it to the Official LightSwitch forums.
By Michael Washington on
2/6/2014 10:30 AM
|
The issues seems to be that when using a DATE or DATETIME field in a RIA service, it sets the field as required. I believe the issue I was experiencing was due to the fact that some rows were NULL, since populating them I am farther along. Now I am at the report side and it just says loading data but nothing shows up. Can you maybe explain how I might could troubleshoot this further. I feel like i am close and I am sure the correct value is being passed but nothing populates.
By Ken Carrier on
2/6/2014 11:34 AM
|
@Ken Carrier - I apologize but unfortunately the comments section in this blog post does not allow technical issues to be resolved. Please make a post to the official LightSwitch forums at: http://social.msdn.microsoft.com/Forums/vstudio/en-US/home?forum=lightswitch
By Michael Washington on
2/6/2014 11:36 AM
|
Here is the forum Michael thanks! http://social.msdn.microsoft.com/Forums/vstudio/en-US/3a8def65-3616-4efc-b660-7255913f622b/creating-reports-in-lightswitch-html-client-loading-data?forum=lightswitch
By Ken Carrier on
2/6/2014 1:11 PM
|
Hi Michael,
Does it work with Sharepoint online? What would be an alternative to create lightswitch reports in office 365?
thanks
By manzil on
2/23/2014 8:30 PM
|
Thanks a lot for this article. Very well explained. I bought your online book recently and just wondering do you have any plan to write Lightswitch with SharePoint app?
How we could make this report works with SharePoint online?
thanks
By manzil on
2/23/2014 8:30 PM
|
@manzil - I do not know if this works with SharePoint because I have not had a chance to do any SharePoint yet. I plan to do something in the future but I do not know when.
By Michael Washington on
2/23/2014 8:31 PM
|
Thank you very much for the article .. Can i use this for an application hosted on Azure?
By yanezricardo on
2/28/2014 3:35 PM
|
@yanezricardo - It should work, but I have not tried it.
By Michael Washington on
2/28/2014 3:36 PM
|
Hello Michael
This approach is possible with CLient Silverlight OOB? Something using the Web Browser Control?
Victor Perez
By Victor Perez on
3/16/2014 10:01 AM
|
@Victor Perez- sorry I have no examples.
By Michael Washington on
3/16/2014 10:35 AM
|
Hello,
First of all, congrats for you tutorial, it is great! I am trying to create a report functionality in my lightswitch application but I am having the following issue: [InvalidOperationException: It is not valid to access this object on the current thread.] This happens in the ProcessRequest method of the Page ReportViewer, can you help me with this?
Thank you very much!
By Jesus Nieto on
7/28/2014 4:45 AM
|
@Jesus Nieto - If my code sample works for you but your own doesn't please open a support case with ComponentOne support on their site. Thank You.
By Michael Washington on
7/28/2014 4:46 AM
|
I know this thread is a little old, but I'm wondering if anybody has managed to get this to work with Lightswitch 2013?
I managed to get pretty far with it, but when I run the app, the ReportViewer control is completely disabled. It looks like it should respond to mouse clicks, but it doesn't. I can see the data it retrieved, but I can't do anything with it. I can't even scroll the control. And the control seems to size to about 400x400 pixels no matter I set in the render event.
If anybody has had better luck with it, I'd love to hear your secrets.
By Wilson on
4/23/2015 1:26 PM
|