May
12
Written by:
Michael Washington
5/12/2011 4:19 AM
Printing in LightSwitch was previously covered here:
http://lightswitch.adefwebserver.com/Blog/tabid/61/EntryId/3/Printing-With-LightSwitch.aspx
The disadvantages of that approach are:
- You have to make a custom control / You have to be a programmer to make reports
- Printing in Silverlight renders images that are slightly fuzzy
In this article, we will demonstrate creating and printing reports in LightSwitch using Microsoft Report Viewer Control.
Note, you will need Visual Studio Professional, or higher, to use the method described here.
We want this Print Invoice Button to open the Report (that we will create later) and pass the currently selected Customer (so the Report will know which Customer to show).
First, add a reference to System.Windows.Browser, by switching to File View in the Solution Explorer, and right-clicking on References in the Client project.
Also, add a reference to Microsoft.VisualBasic.
Right-click on the Print invoice button and select Edit Execute Code.
In the object tree on the Screen, we replace all the previous code with the following code:
using System;
using System.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Framework.Client;
using Microsoft.LightSwitch.Presentation;
using Microsoft.LightSwitch.Presentation.Extensions;
using System.Windows.Printing;
using System.Windows;
namespace LightSwitchApplication
{
public partial class CustomersListDetail
{
partial void PrintInvoice_Execute()
{
// Only run if there is a Customer selected
if (this.Customers.SelectedItem != null)
{
Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() =>
{
System.Text.StringBuilder codeToRun = new System.Text.StringBuilder();
codeToRun.Append("window.open(");
codeToRun.Append("\"");
codeToRun.Append(string.Format("{0}", String.Format(@"{0}/Report.aspx?CustomerID={1}",
GetBaseAddress(), this.Customers.SelectedItem.Id.ToString())));
codeToRun.Append("\",");
codeToRun.Append("\"");
codeToRun.Append("\",");
codeToRun.Append("\"");
codeToRun.Append("width=680,height=640");
codeToRun.Append(",scrollbars=yes,menubar=no,toolbar=no,resizable=yes");
codeToRun.Append("\");");
try
{
System.Windows.Browser.HtmlPage.Window.Eval(codeToRun.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message,
"Error", MessageBoxButton.OK);
}
});
}
}
#region GetBaseAddress
private static Uri GetBaseAddress()
{
// Get the web address of the .xap that launched this application
string strBaseWebAddress = System.Windows.Browser.HtmlPage.Document.DocumentUri.AbsoluteUri;
// Find the position of the ClientBin directory
int PositionOfClientBin =
System.Windows.Browser.HtmlPage.Document.DocumentUri.AbsoluteUri.ToLower().IndexOf(@"/default");
// Strip off everything after the ClientBin directory
strBaseWebAddress = Microsoft.VisualBasic.Strings.Left(strBaseWebAddress, PositionOfClientBin);
// Create a URI
Uri UriWebService = new Uri(String.Format(@"{0}", strBaseWebAddress));
// Return the base address
return UriWebService;
}
#endregion
}
}
Deploy The Application and Add The Report
In the Properties for the project, change it to a Web application and click the Publish button.
It is recommended that you simply deploy the application to your local computer and then copy it to the final server after you have added the reports(s) .
After we have Deployed the application, we open the Deployed application in Visual Studio.
When the application is Deployed, a database is created (or updated). We will open this Database and add a View.
We design a View and save it.
In Visual Studio we Add New Item…
We add a Report to the project.
We use the New button to create a connection to the database. This connection is only used to design the Report.
We will add code in a later step that will provide data to the Report at run-time.
We complete the Report and save it.
After designing the report, we place a Report Viewer Control on an .aspx page (we also need to add a ScriptManager control to the page).
We add a Linq to SQL class to the project that contains the View.
The following code, in the code behind for the page, is used to accept the Report parameter (the selected Customer), and to display the Report in the Report Viewer Control.
public partial class Report : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["CustomerID"] != null)
{
if (!Page.IsPostBack)
{
ShowReportViewer();
}
}
}
#region ShowReportViewer
private void ShowReportViewer()
{
this.ReportViewer1.ProcessingMode = ProcessingMode.Local;
this.ReportViewer1.LocalReport.ReportPath = Server.MapPath("~/Report.rdlc");
ReportViewer1.LocalReport.DataSources.Add(
new ReportDataSource("DataSet1", LoadData()));
}
#endregion
#region LoadData
private DataTable LoadData()
{
int CustomerID = Convert.ToInt32(Request.QueryString["CustomerID"]);
DataClassesDataContext db = new DataClassesDataContext();
var result = from LoansAndCustomers in db.vwLoansAndCustomers
where LoansAndCustomers.Id == CustomerID
select LoansAndCustomers;
Utility objUtility = new Utility();
DataTable dt = objUtility.LINQToDataTable(result);
return dt.DefaultView.Table;
}
#endregion
}
Note, that this class is used to convert the Linq to SQL query into a DataTable needed by the DataSource for the Report.
// From: http://www.c-sharpcorner.com/UploadFile/VIMAL.LAKHERA/LINQResultsetToDatatable06242008042629AM/...
// ...LINQResultsetToDatatable.aspx
public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
DataTable dtReturn = new DataTable();
// column names
PropertyInfo[] oProps = null;
if (varlist == null) return dtReturn;
foreach (T rec in varlist)
{
// Use reflection to get property names, to create table, Only first time, others will follow
if (oProps == null)
{
oProps = ((Type)rec.GetType()).GetProperties();
foreach (PropertyInfo pi in oProps)
{
Type colType = pi.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()
== typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
}
DataRow dr = dtReturn.NewRow();
foreach (PropertyInfo pi in oProps)
{
dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
(rec, null);
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
Also note, that we don't actually pass the parameter to the Report Viewer control. With a .rdlc report, we simply provide the data for the report. We must filter the Linq query to filter the report.
What we are doing is passing the parameter to the .aspx page and then creating a query to pull up only the data we need and supplying it to the Report.
Note, you can see this site if you have any questions about the Report Viewer Control: http://www.gotreportviewer.com
When we run the Deployed application, select a Customer, and then click the Print Invoice Button…
The Report is displayed in a popup window.
You will need to use ASP.NET 4.0, and install the Microsoft Report Viewer 2010 Redistributable Package on the web server that displays the report.
Download
You can download the code at this link.
56 comment(s) so far...
This is very nice, I am looking forward to giving it a go this weekend. Thanks for all your hard work.
By Namoguy on
10/26/2010 7:59 PM
|
Excellent article! Was looking forward to reading it since you tweeted of its pending publishing a few days ago. The article describes how to fill a significant hole in the Lightswitch story-- the ability to create reports. Will be exploring / prototyping from this article over the weekend.
Thanks much for the great work you're doing in helping the community!
By Dan Moyer on
10/27/2010 5:07 AM
|
@Namoguy - @Dan Moyer - Please provide feedback in the LightSwitch forums social.msdn.microsoft.com/Forums/en-us/lightswitchgeneral/threads so any issues can be properly discussed :)
By Michael Washington on
10/27/2010 6:13 AM
|
Thanks Michael! Appreciated.
By wemba on
12/23/2010 6:30 AM
|
I am having trouble getting this to work in my application. It throws a "The DOM/scripting bridge is disabled." error. In think this has to do with running the application Out Of Browser and that it is a Silverlight issue. I have it deployed to run as a Desktop Client, 3-Tier Deployment. It throws the InvalidOperationException in the GetBaseAddress region, on:
string strBaseWebAddress = HtmlPage.Document.DocumentUri.AbsoluteUri;
Is there any way to get around this in the deployment I am using?
Also, in the GetBaseAddress region you refference a ClientBin directory? Is that correct?
Thank you!
By Shawn Gentry on
1/7/2011 2:06 PM
|
@Shawn Gentry - I am sorry but I do not have any examples to address your situation.
By Michael Washington on
1/7/2011 2:07 PM
|
Maria says hello hello I'm learning and I have LS q do the following for a project
I have a school that wants to see the students' scores on the web for which when a student enters the system with your password can view the newsletter notes that student only
when one is logged porfesor skills is to enter something simple very complicated not think you can do in ls
By Mae on
2/9/2011 8:13 AM
|
@Mae - LightSwitch Can do what you require, however, you will want to wait until it is out of Beta before starting any real applications with it.
By Michael Washington on
2/9/2011 9:17 AM
|
any clue for when it is out of Beta ????
By joan on
2/25/2011 5:07 AM
|
Once again you've explained something I'd never have figured out on my own. As Namoguy said, thanks for all the hard work.
By Richard Waddell on
4/21/2011 11:11 PM
|
Note. This Blog has been updated to the latest LightSwitch and it now has a code download.
By Michael Washington on
5/18/2011 11:58 AM
|
Hi Michael,
I attempted to utilize your approach on a project of mine, but I converted the code to VB using teleriks converter. It all compiles both in the lightswitch project and the web project that is published. However, when I press the button to print the report, the page comes up, but remains completely blank- not even the headings show up.
The URL shows that it is calling the page http://localhost:524721/productservice/Report.aspx?PRODSERVID=6 - the item i am picking in the grid.
I know you obviously dont have my code, but any ideas as to under what conditions the data wouldnt show up? Related to that I am not sure if the CustomerID you have in your example is tied to anything anywhere in the background? ie How does the code know that the CustomerID used as a paramater name is really related in some fashion to the Id in the linq to sql attribute for the customer entity?
I should mention that when I attempt to debug the code at the website itself and step through it, its like it never gets to or goes through that code. So in effect its like just the window that is called from the lightswitch application and presents itself, but never goes further to kick of report viewer- ie doesnt even get to the logic.
If I call that page from the ls application, but simply hardwire the reportviewer to the design source for runtime- it renders the report in its totality without filtering.
Hope its not an inappropriate or dumb question.
Any thoughts from the above description?
PS- did download your c# code to make sure that i was replicating the equivalent in VB
By Lyndon on
5/22/2011 4:25 PM
|
@Lyndon - Please post any questions to the forums. Thanks.
By Michael Washington on
5/22/2011 4:26 PM
|
Hi Michael
Thank you for the work you are doing and for sharing their knowledge and results.
Very good job.
Just a suggestion, it would be helpful if the Home page of this site could see the complete list of all these good jobs.
Jaime
By Jaime on
6/3/2011 1:28 PM
|
@Jaime - Ok we are now listing the latest Blogs on the front page. We of course cannot list them all because there are too many and they grow every week :)
By Michael Washington on
6/3/2011 1:29 PM
|
I just purchased the PDF file, and glancing through a few pages, I love it. Micheal please write a full book on Developing Applications, using Visual Studio LightSwitch, and provide several examples.
Thanks.
Gabimb.
By gabimb on
7/29/2011 12:52 PM
|
Gabimb - Thank you for the feedback. I worked weeks on that E-Book :)
By Michael Washington on
7/29/2011 12:59 PM
|
Hi Michael,
Nice article (as usual).
I'm assuming this runs in the browser. How do you address security issues? Can't a user simply pass in the url that's generated and modify it to show a customer or some other data that they should not have access to?
Thanks, Dave
By fishy on
8/24/2011 7:09 AM
|
@fishy - I did not put any security in to keep the example simple. However, it should be possible to create a "token string" for each user and pass that as a parameter to the report. The report can check the database for the proper token for the user.
By Michael Washington on
8/24/2011 7:34 AM
|
thanks mate! this tutorial saved me!!!
By SeasonJo on
10/8/2011 10:15 AM
|
Hi Michael,
Utility objUtility = new Utility(); (In LoadData() method)
Where is this Utility class?
By Sheen on
10/20/2011 4:33 AM
|
@Sheen You can download the code to see all the code.
By Michael Washington on
10/20/2011 4:34 AM
|
Hi Michael,
I think I did everything as described but I get 'Argument 'Length' must be greater or equal to zero' error dialog when 'Print invoice' is clicked. Any ideas? Thanks.
By AlexK on
11/16/2011 1:20 PM
|
Got it. private static Uri GetBaseAddress() { // Get the web address of the .xap that launched this application string strBaseWebAddress = System.Windows.Browser.HtmlPage.Document.DocumentUri.AbsoluteUri;
// Find the position of the ClientBin directory int PositionOfClientBin = System.Windows.Browser.HtmlPage.Document.DocumentUri.AbsoluteUri.ToLower().IndexOf(@"/default"); if (PositionOfClientBin >= 0) // Strip off everything after the ClientBin directory { strBaseWebAddress = Microsoft.VisualBasic.Strings.Left(strBaseWebAddress, PositionOfClientBin); } else { strBaseWebAddress = strBaseWebAddress.TrimEnd('/'); }
// Create a URI Uri UriWebService = new Uri(String.Format(@"{0}", strBaseWebAddress));
// Return the base address return UriWebService; }
By AlexK on
11/17/2011 6:16 AM
|
Hi,
I'm getting the same error as AlexK.
'Argument 'Length' must be greater or equal to zero' error dialog when 'Print invoice' is clicked.
Can I ask what was the solution please? Thanks
By ksan on
12/15/2011 10:28 AM
|
Hi, I figured it out. I wasn't excuting the button from the default page so the check for PositionOfClientBin = System.Windows.Browser.HtmlPage.Document.DocumentUri.AbsoluteUri.ToLower().IndexOf(@"/default");
wasn't working. Instead to get the strBaseWebAddress, I did strBaseWebAddress = System.Windows.Application.Current.Host.Source.Host.ToString(); strBaseWebAddress = "http://" + strBaseWebAddress;
By ksan on
12/15/2011 12:08 PM
|
Great job! Wonderingly if it's possible call WinForm RS report viewer from LightSwitch. I was used to WinForm dev.
By ayxu on
12/20/2011 7:26 PM
|
Hi michael , what is Microsoft.LightSwitch.Design.svc include in your project
By oan on
1/24/2012 10:20 AM
|
@oan - That is a default file created by the LightSwitch framework
By Michael Washington on
1/24/2012 10:20 AM
|
Hi Michael, I attempted to apply your approach on a project of mine, I arrived to the step where I need to open the deployed application in Visual Studio, Within the "Publish" folder I would like to know which file to open with Visual studio?
By Madock on
2/28/2012 3:15 PM
|
@Madock - You are not opening an existing file. You are creating a new one.
By Michael Washington on
2/28/2012 3:16 PM
|
Hi Michael,
In your reply to @fishy earlier on the security, you mentioned "it should be possible to create a "token string" for each user and pass that as a parameter to the report. The report can check the database for the proper token for the user."
Would it be possible to point me in the right direction to learn how to do this or if you happen to have any examples I can have a look at?
Many thanks.
Best regards, CT
By CT on
3/15/2012 2:41 AM
|
@CT- Sorry I have no examples.
By Michael Washington on
3/15/2012 4:14 AM
|
Michael, Thank you for the post. Please forgive my ignorance, but is there a way to combine the two projects for ease of deployment or is it always necessary to deploy twice? I'm having difficulty moving my project from dev to production environment. Also, would additional reports require additional projects or could the same report project be used for additional reports? Thank you again! brian
By brian norberg on
3/15/2012 1:44 PM
|
@brian norberg - It is possible but it would require editing the .proj file to add the .aspx file tp the manifest. I cover that process elsewhere on this site with the help desk article under advanced.
By Michael Washington on
3/15/2012 1:47 PM
|
Great article on LightSwitch Michael! With just a little effort anyone can make this example ready for production adding just a few security measures.
I've read your e-book before and I can say you are really good with LightSwitch! I'll be checking out more on this blog for examples and other applications!
Thanks and keep up the good work mate.
Alfred, Step Down Transformer
By Alfred Manch on
3/30/2012 5:19 PM
|
hi, at first thank you for every tutorial!
one question,how to use the report if client is desktop?
thankyou nico
By nico on
4/27/2012 7:54 AM
|
@nico - this does not cover the desktop. I have no examples. Look at what DevExpress has to offer.
By Michael Washington on
4/27/2012 7:54 AM
|
Hi Michael,
Utility objUtility = new Utility(); (In LoadData() method)
Where is this Utility class?
By rajeev sekhar on
5/4/2012 9:51 PM
|
Sorry.. I got it...................
By rajeev sekhar on
5/5/2012 12:12 AM
|
Hi Michael,
I'm trying to implement a lightswitch application to a client, using the web deployment with visual studio 2010
It's possible, instead open the browser in a new window, open it directly in the screen? Or this option, only works with the desktop deployment?
Regards,
João
By João Sousa on
9/12/2012 8:51 PM
|
here we just pass parameters for the web page as query string , and based on the parameter value dataset is filled and report is fired , now in Light Switch Application i have a Query Screen which filter may data based on many query parameters , my questions is how to pass this filtered list , Or ID's on [LS Grid] and pass then external web page so i can Generate my Report using crystal report.
By omar awwad on
2/19/2013 1:34 PM
|
Hi Michel.
Does exist the same example in vb.net?
Thanks in advance
By Roberto Tomassini on
5/9/2013 6:38 AM
|
@Roberto Tomassini - Sorry, no.
By Michael Washington on
5/9/2013 6:39 AM
|
Hi Michael,
thank you for your fantastic article.
I deployed the application successfully, but the following error appears:
Validation error. method not found "System.String Microsoft.LightSwitch.Model.Extensions.Internal.ModelUtilities2.DisplayNameOrName (Microsoft.LightSwitch.ModelIModelItem).
Anyone can help?
Thanks!
By MR. W on
7/5/2013 7:49 AM
|
@MR W. - I am sorry I do not have any idea about that error, However, please see the following link for LightSwitch deployment issues: http://msdn.microsoft.com/en-us/library/vstudio/ff872288.aspx
By Michael Washington on
7/5/2013 7:51 AM
|
Michael any recommendation when the application and the database is in windows azure? as send Connection credentials for example? Very grateful for your help. Greetings from South America
By Joe Caballero on
7/5/2013 8:50 AM
|
@Joe Caballero - I have no examples, sorry.
By Michael Washington on
7/5/2013 8:51 AM
|
RDLC report can't show print button .why?
By yunzhongpiao on
3/1/2014 7:55 AM
|
@yunzhongpiao - On certain web browsers the print button doesn't show.
By Michael Washington on
3/1/2014 8:01 AM
|
hii, i have problem, the print button dontshwing in report viewer when deploy the project thanks
By smail on
3/24/2014 3:40 AM
|
@smail - On certain web browsers the print button doesn't show. The export will always work.
By Michael Washington on
3/24/2014 3:41 AM
|
In this tutorial,
It says"We add a Linq to SQL class to the project that contains the View." How to do this?
I also noticed that in the App_Code node in the website project, there is a node called DataClasses.dbml . I think this node is the result of the
"We add a Linq to SQL class to the project that contains the View." operation.
Isn't it?
By whlxy on
6/6/2014 5:07 AM
|
@whlxy - For help creating a SQL View just Google "Creating a View in SQL Server". Also, yes DataClasses.dbml is created when you add a Linq To SQL Class to the project.
By Michael Washington on
6/6/2014 10:59 AM
|
Hi,Michael! I know how to creat a sql view in Sql Server.
But I don't know how to add a Linq To SQL Class to the project. In this image,http://lightswitchhelpwebsite.com/portals/0/blog/5f3b40a5134d_127AD/image_thumb_16.png
It says " Create methods by dragging items from Server Explorer onto this design surface.
And I think you dragged the vwLoansAndCustomers on to that design surface. For me I don't know which design surface you have dragged the view to. I don't know how to do this step, It seems that there are some operation before you can drag.
Can you tell me what are those operations?
By whlxy on
6/6/2014 12:06 PM
|
@whlxy - Sorry I can't find a step-by-step example. Basically you make a SQL View in SQL Server then drag and drop it on the Linq To SQL design surface. I am sorry that it falls outside of the primary focus of this site. Also this is a very old article. There are newer articles at: http://lightswitchhelpwebsite.com/Blog/tabid/61/tagid/11/Printing.aspx
By Michael Washington on
6/6/2014 2:42 PM
|