(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

Building a Silverlight Line-Of-Business Application – Part 6

(73 votes)
Chris Anderson
>
Chris Anderson
Joined Sep 29, 2008
Articles:   8
Comments:   62
More Articles
44 comments   /   posted on Jan 05, 2009
Categories:   Line-of-Business

This article is compatible with the latest version of Silverlight.

Introduction

In Part 5 of this series I looked into creating a form to maintain the details of products in the inventory. In this article I will look at implementing reporting functionality within the Silverlight application.

Source Code and Live Demo*

Instructions on setting up the sample project can be found in Part 1.

*To log into the sample application use the following Username: demo and Password: demo

Be sure to check all articles of the series: Part 1, Part 2, Part 3, Part 4, Part 5 and Part 6

Reporting Requirements

Businesses need to be able to store their data, but they also want to get information out of the system to track and monitor various aspects of the business such as performance, cash flow, forecasts, sales vs targets, etc. An ideal means of achieving this is through implementing reporting functionality in the application. A report generally consists of data retrieved from one or more databases inserted into a predefined template – often with some sort of processing in between to turn the data into useful information. Reports can range from the extremely simple to the extremely complex, but both follow the same workflow from an application perspective. At runtime, data is extracted from the database and is passed through to the report generator/writer which processes the data and formats the results suitable for printing in a human readable form. The complexity of processing the data and formatting the results is handled by the report generator based upon the rules defined in the template. Users won’t always want to have to produce reports for information that they regularly monitor but don’t print – this functionality is better implemented within the dashboard. Therefore reporting is most appropriately used when printing is required (which it is in most line of business applications).

Examples of simple reports include invoices and data printouts, which require minimal processing and generally just insert data from a database directly into the report. More complex reporting may involve mining the data in the database to determine patterns or relationships (correlations) between various data points, or create predictive models upon which management can base their ongoing tactics and to help determine their future strategies. Some reports may take some time to produce when a lot of processing is required, and if generating reports places a high load on the web server then this process may be offloaded to a separate dedicated server (such as SQL Server Reporting Services). So to throw in a few buzz words, reporting helps enable business intelligence and knowledge management from within your line of business application.

There are reporting solutions for Windows Forms and ASP.NET provided with each copy of Visual Studio (Crystal Reports for Visual Studio in the Professional or higher editions, and Visual Studio Report Designer in the Standard or higher editions and in the Visual Web Developer 2008 Express Edition after installing an add-in). However, neither of these generates reports that can be viewed or printed within a Silverlight application. The only existing solution I have found is a third party solution called Report Sharp-Shooter for Silverlight by Perpetuum Software. I haven’t tried it personally, though based upon the online demo and the feature list you can’t print the report directly from the Silverlight application – the user still needs to export it to another format (such as a PDF file) before they can print the report, which is not the streamlined solution I’m trying to achieve. The reason why printing wouldn’t be implemented is because in actual fact Silverlight currently has no ability to send data to a printer. Therefore we need to look outside Silverlight for a solution.

The strategy I have decided to use therefore is to use existing reporting tools to generate the reports and display these somehow within the application. I chose to focus on generating the reports using the Visual Studio Report Designer as it’s a reasonably capable reporting tool (it uses the same template format as used by SQL Server Reporting Services), and it’s the reporting tool that all Silverlight developers can use, being provided with Standard and higher editions of Visual Studio. Note that Microsoft has just released an add-in to provide the Visual Web Developer 2008 Express Edition with a report builder. They previously had one for the 2005 edition but had not up until now released a version for the 2008 edition. If you are using the Express Edition, you can download the add-in here.

The output of the reporting engine can be either HTML (when hosted within the ASP.NET Report Viewer Control), an Excel document, an image, or a PDF document, each of which can be displayed within a browser (HTML and images natively, Excel and PDF documents by browser plug-ins). Only the image rendering however can be displayed directly within a Silverlight application, but is not a particularly suitable option due to the large file size of the images and that the quality of the printouts would be low resolution when attempting to print them. Therefore we need to look at means of rendering the report outside of the Silverlight application, using the capabilities of the browser instead.

Of the three remaining options we can exclude rendering to Excel as it would only generally be appropriate to do so when generating matrix or table based reports. We can now (using the 2008 version) print directly from ASP.NET’s Report Viewer control, but it requires the installation of an ActiveX control which will only work in Internet Explorer running on Windows (not Macs) and not within Firefox. You want your Silverlight application to run cross browser and cross platform so I consider this to be an unnecessary restriction to put on your application in most scenarios, and I believe printing is a vital feature for implementing reporting. This leaves PDF as our only viable option, though it does provide the functionality we require. PDF documents display on the screen exactly as they appear on the printed page, they can be printed directly from within the browser where they are being viewed, they can be saved to the user’s hard disk (or a network drive) for archiving purposes, they can be easily emailed to colleagues, and they can be published to content management / collaboration / document management systems such as Microsoft SharePoint. In other words it provides the best solution to fit the majority of report display requirements.

As noted however, you cannot view a PDF document from within a Silverlight application (without writing an entire PDF renderer for Silverlight). Opening the report up in another browser window would be a possible solution but is not particularly suitable in all cases as it separates the display of the report from the application. Therefore we need to look to other options to achieve this. Our application was designed to fill all the available area in the browser window, so having the application and the report within the same browser frame is not really a viable solution. There is a technique however to overlay a part of the application with an IFrame (contained within the same HTML file that hosts the Silverlight application) to achieve the required effect.

HTML Viewer Control

To support displaying an IFrame within the application I decided to wrap the functionality into a reusable user control. This way wherever support is required in this or other applications for displaying HTML content within the application itself we can easily drop it in. This control creates an IFrame in the underlying html page using the HTML Bridge, and is overlaid on top of the Silverlight plug-in, with the HTML content to display loaded within it.

Before we describe how this control works, let’s take a quick detour to discuss the HTML Bridge. Essentially the HTML Bridge is the means to interact with the underlying browser and document object model (DOM) from a Silverlight application. You may also see this referenced as HTML DOM Interoperability. Throughout this article I use the HTML Bridge to provide various features such as opening a popup window, creating elements in the DOM (such as an IFrame), inspecting the DOM (checking properties of the Silverlight plug-in), creating cookies, and handling JavaScript events. To access the HTML Bridge, add a reference to the System.Windows.Browser namespace, and then you can access the DOM of the underlying HTML document that is hosting the plug-in via the static HTMLPage class.

Now that we know a bit about the HTML Bridge let’s look at some of the issues that we will face in displaying an IFrame over the top of our Silverlight plug-in. The primary issue that we face is that by default the Silverlight plug-in is in “windowed” mode, where the plug-in handles rendering the Silverlight content in its own window, which is on top of any HTML content in the underlying HTML document. Therefore even though we are able to create the IFrame in the underlying HTML document it won’t be visible as our Silverlight plug-in occupies the entire browser area, rendering on top of any HTML content in the DOM of the page (regardless of the z-index of the plug-in or the IFrame). Therefore we need to turn this windowed mode off so that the browser is in charge of the rendering instead of the Silverlight plug-in, and then our Silverlight content will be rendered alongside the underlying HTML content. There are performance issues however in placing the browser in charge of the rendering, so the decision to use windowless mode needs to be carefully considered. Silverlight is optimised for rendering complex animations and video and there will be a significant performance loss in these two areas when using windowless mode. Considering the fact that we are building a line of business application here the loss in rendering performance is probably not going to affect us in most cases, so the benefits in this case should outweigh the costs. Karl Erickson has an excellent blog entry containing other limitations of windowless mode that is worth reading – the link can be found in the Resources at the end of this article.

To enable windowless mode we need to open the ASPX page hosting the Silverlight plug-in, find the asp:Silverlight tag, and add a Windowless attribute – setting its value to “true”. When this renders to the output page some param tags are added as children of the plug-in and this property will be one of them. Since we are creating a reusable control it’s worth checking to make sure the developer has turned on this windowless property and raise an exception if not, in order to save confusion as to why the IFrame isn’t being displayed. With the HTML Bridge we can navigate through the DOM of the page and ensure this property is turned on. First we need to get a reference to the plug-in element (which is rendered as an object tag). Rather than searching for the object tag in the page, we can simply get a reference to it using HTMLPage.Plugin. Then we can enumerate through its children looking for param tags that have a name attribute of “Windowless”. If the tag isn’t found or its value is set to False then we can throw an exception.

The next step is to create the IFrame in the underlying HTML page. The IFrame is contained within a DIV element so that we can set its position properly. For this DIV we’ll set its z-index to 99 (so it displays on top of other controls, assuming their z-index is less than 99), and set its positioning mode to “absolute”. This means we can set its position by its coordinates in the browser window. We can then append this DIV as a child of the FORM tag in the DOM, and append the IFrame element as a child of the DIV tag.

Now that we have created the required elements in the DOM we need to position and size them. As previously mentioned this involves setting the coordinates and size of the DIV, and we will also set the height and width of the IFrame to support multiple browsers (in some browsers the IFrame fills the area of the DIV, and in others it doesn’t). This involves working out the location of the control with reference to the application root visual element (ie. the whole area occupied by the Silverlight plug-in) by creating a transform object to transform the coordinates of the two and relating (0, 0) on the control to (0, 0) on the application root visual element. This gives us the coordinates of the control with reference to the application root visual element, but not necessarily with reference to the browser window itself (if the Silverlight control is not located at (0, 0) to the browser window). Therefore for completeness we should calculate the offset of the Silverlight plug-in in the underlying page (moving up the DOM and adding offsets of each parent element) and add that to our calculations. As our Silverlight application is filling the entire browser window it will be located at (0, 0) making this calculation unnecessary, so I have chosen to make this an assumption and forgo these additional calculations. Therefore we now can use these coordinates to set the “left” and “top” properties of the DIV, and the “width” and “height” properties are simply the width and height of the control.

With writing a control such as this where the content being displayed is not being rendered by Silverlight we need to take resizing of the control into account. If the control is resized (such as if the browser window was resized or a grid splitter was implemented that enabled the user to resize or move the location of the control) we need to handle the LayoutChanged event of the control and adjust the size and location of the IFrame accordingly. Note that I don’t handle the SizeChanged event for this purpose – the reason being that if the control location was simply moved (rather than resized) the SizeChanged event is not raised. Therefore although the LayoutChanged event is raised even when the control hasn’t been moved or resized (and can be raised many times for many reasons as it is raised when anything occurs in the visual tree), it’s the only event that will handle all situations – even if it isn’t ideal (I try to never handle this event if an alternative is available due to the numerous times and purposes that it can be raised).

I have included support for monitoring when the page has loaded (handling the JavaScript onLoad event raised by the IFrame via the HTML Bridge), in turn raising an event on this control to notify the application as such. This could potentially be useful in showing an animation and/or message in the footer of the application (as server data requests do) indicating that the application is communicating with the server. Capturing this DOM event in Silverlight is actually quite easy – when creating the IFrame I could just use the AttachEvent method on the HTML element, specifying the JavaScript event to capture and the .NET method to handle it. However we strike a problem in loading a PDF in the IFrame as for some reason the onLoad event is never raised (I assume it is because a separate plug-in takes over loading the page), though it is raised correctly for HTML pages. As our reports will be PDF files we won’t be able to use this feature in our application to indicate the fact that server communication is in progress, though the functionality has been included in this control for reuse purposes when displaying HTML pages. However for our purposes an alternative is required so that the user knows something is happening.

What I was trying to achieve as a substitute was to display a “Please wait – loading...” message in the control area. I discovered that if I set some HTML locally to display immediately in the IFrame and navigated the IFrame to the report URL on the server, then this would continue to display until the report had been retrieved from the server and the Adobe Reader plug-in had loaded itself and the report. So if I created some simple HTML showing the please wait message and set it as the content of the IFrame then this would display until the report had loaded.

 

I attempted to build up the HTML to display using the HTML Bridge functions to create the DOM for the page, however IE displayed this in quirks mode as there was no way to set the DOCTYPE for the loading page via the DOM – displaying the page differently to how it was displayed in Firefox and without the expected formatting. Therefore I needed to find an alternative means of creating and loading this page locally. I then discovered that a reference to the empty document created in the IFrame automatically when it is created can be obtained. We can then open it for direct HTML content writing, write the entire HTML document to be displayed (including the DOCTYPE, html, head, and body tags), and then close it. This document would then be displayed in the IFrame. The open, write, and close functions are not available via the HTML Bridge but can be called using the Invoke method on the document object.

Note that there appears to be a bug in Internet Explorer which I haven’t found a workaround for. Even after the report has loaded, the progress bar in the status bar continues to show. This appears to be due to a combination of writing of writing directly to the document in the IFrame then navigating to a different page – if I comment one or the other out the progress bar is hidden correctly, but using both together leaves it visible. This problem does not appear to occur in Firefox.

The final issue we need to find a solution for is how to know when to remove the IFrame from the DOM. Silverlight user controls don’t have a Closing or Closed event, the Dispose event when implementing IDisposable isn’t automatically called, and the destructor/finaliser being called is unreliable as it relies on the whims of the garbage collector as to when the control is cleaned up to be called. In any case we’ll implement the IDisposable interface and have this method remove the IFrame from the DOM. We can then call this from our parent user control, but again we hit another problem – our parent doesn’t know when it is being closed either! Since our underlying framework handles the navigation between “pages” and to enable this each “page” user control implements our IContentPage interface, we can add a Close method to this that the framework will call before it removes the user control from the visual tree to open another one. This is the method I chose, and from the Close method in the host/parent user control the Dispose method on the control can be called. As an additional feature to this, the Close method takes a new CloseArgs event arguments object as a parameter. This object has a Cancel property which if set to true will cancel the closing of the “page” user control and stop the next one from being opened.

Reports

As previously described, the reports will be generated using the local report viewer (ie. the engine that generates reports from templates created using the Visual Studio Report Designer) and rendered to PDF files. These will be streamed directly to the user’s browser and displayed in the HTML Viewer control. To enable this we’ll create an HTTP Handler in our web project to serve these reports to the Silverlight clients. Note that you will need to add a reference to the Microsoft.Reporting.WebForms DLL to your web project to enable reports to be generated.

I have created a base class to permit reusability of the HTTP Handler code to handle report requests in a generic fashion (BaseReportHandler). This class handles authenticating the user, finding the renderer for the report they have requested (soon to be discussed), checking if the user is authorised to view the report, requesting that the renderer handle the report generation, then streaming it back to the client as a PDF file. All that needs to be done is to create your own HTTP Handler, inherit from BaseReportHandler, and override the RegisterRenderers method. The purpose of this method is to populate the ReportRenderers dictionary from the base class, defining all the supported renderers with the key as their name and the value as a string containing their namespace and class name. An example is as follows:

protected override void RegisterRenderers()
{
    ReportRenderers.Add("ProductDetails", "AWWeb.Reports.Products.ProductDetailsReportRenderer");
    ReportRenderers.Add("ProductCatalog", "AWWeb.Reports.Products.ProductCatalogRenderer");
}

When a report is requested, the base class will then find the entry matching the ReportName query parameter from the HTTP request and instantiate the associated report renderer using reflection. Now I should explain what I mean by report renderer. This is a pattern that I have created to simplify the generation of reports. Often there are a few processes in generating a report (such as populating the report with data, populating subreports with data, etc) and properties to set (such as the report path, name, authorisation rights, orientation, size, etc) that are specific to that report. Rather than attempting to create an overly complex generic solution, what I do is offload responsibility for generating the report to its report renderer class. This class will handle all the creation and population of the report and return it back to the HTTP Handler as a LocalReport object ready for streaming back to the client. Of course there is a base class to help manage this workflow named BaseReportRenderer. Each report should have a renderer class that inherits from BaseReportRenderer and overrides the appropriate methods and properties. A simple workflow implemented in the GetReport function in the base class is to create a LocalReport instance, set the location to the report template, populate the report data sources, and return this LocalReport instance back to the HTTP Handler. If this is the required workflow we can just override the ReportPath property and the PopulateReportDataSources function in our report renderer (the minimum requirements for any report to be rendered). For more complex scenarios you can override the GetReport function to have full control over this workflow.

The PopulateReportDataSources function in our report renderer is where most of the work in the renderer is done. This function needs to obtain the required data for the report from the database and pass it to the LocalReport instance. The Report Viewer control can take in either DataTables or collections of objects as a data source. Ideally we’d like to go through our entity framework model to populate the report, and since I prefer working with objects over DataSets/DataTables I decided to go with the collections of objects method. For a collection to appear as a project data source in the Report Builder a class in the project needs to have a static method that returns a collection (such as a List or Array) of objects. You’ll note that we can’t simply select entities from our Entity Framework model when building a report because of this requirement for a static method. In any case, reports often require data combined from multiple entities so we should create our own data source class to populate the report with, much like the summary DTO classes that we pass back to the Silverlight application to populate lists. To enable this, we’ll create a simple class containing only properties to hold the data, and a static Get method to run the query on our Entity Framework model that returns a populated collection of itself. This class may be shared between multiple reports if they use the same data source and query, or it may be specific to just one report. The PopulateReportDataSources function in our report renderer can then call the static Get method and assign the results to the appropriate data source on the report.

We need to consider that the query that returns the data to populate the report may need to take some parameters to include in its where clause. These should be the parameters of the static Get function to be set by the report renderer, but some of these parameters will not be static values that can be hard coded into the renderer. Instead these values may differ between requests (such as a report that prints out the details of a product based upon the product ID of the product they select to print them for). In the base report renderer class I have a Parameters property (a Name Value Collection) that the base HTTP Handler will assign all the HTTP request query parameters to. The report renderer can then find the required parameters and their values from this to pass through to the static Get function of the data class.

To limit the users who are permitted access to a report you can override the IsUserAccessAuthorised property in the report renderer and determine based upon the user’s role whether they should be permitted access to the report. You may also wish to limit what data the user is permitted to view by their user ID or role (such as only allowing a sales person to view a list of their own sales). This should be implemented in the PopulateReportDataSources function as a part of the where clause in your LINQ to Entities query.

It’s important to implement security on your reports as they may contain the most sensitive business data which you would not want anyone to obtain access to. Another function security can provide is to filter the data in a report to contain only the data that that user has the rights to view whilst using a common report template (such as permitting a sales person to view their own sales figures but no one else’s). We have a dilemma though. Previously we have been passing the user credentials to the server in the SOAP message header of each WCF service call (see Part 3 for more details). However, when requesting a report we won’t be making a WCF service call – in fact we won’t be making a web request at all – the browser will be making the request itself! Therefore we lose control over the request and lose the ability to insert the credentials into it. This leaves us with two options to pass the credentials to the server – via query parameters in the url that requests the report, or by creating a cookie containing the details (which will automatically be included as a part of any request to the server). As the url for each page request is stored in the browser’s history and is visible in the address bar, using query parameters is out of the question. Therefore creating a cookie containing the details is the only reasonable solution. What I have done is create a short lived cookie (30 seconds lifetime) before each report request containing the user name and password for the user. Details on how this cookie was created can be found later in this article in the HTML DOM Interoperability section. The HTTP Handler that generates the reports will retrieve the cookie and validate the credentials and ensure the user is authorised to access that report.

To create the security cookies we need to use the HTML Bridge again. I wrapped some functions to work with cookies in a class (imaginatively titled Cookies), under the Utilities namespace/folder. To set a cookie using the HTML Bridge the following code is required:

string cookie = key + "=" + value + ";expires=" + expiryDate.ToUniversalTime().ToString("R");
HtmlPage.Document.SetProperty("cookie", cookie);

Despite having wrapped this in a reusable function, there are two noteworthy aspects that I thought I’d point out. As you can see, to set a cookie you set the value of the cookie property of the document. However this doesn’t overwrite the existing cookies, instead any cookie that exists with the same key will have its value and expiry updated, and if the key doesn’t exist then the cookie will be added to the collection. The other aspect to note is that when setting the cookie expiry the time needs to be converted to UTC time rather than the local time. Most examples I have seen in relation to writing cookies in Silverlight don’t include this, thus cookies may live for a longer (or shorter) period than would be expected. Although we aren’t currently using them I also added Get and Delete functions for cookies to the utility class.

Once again I will recommend securing your server communications with SSL. The user credentials are being passed to the server in plain text and using SSL is the only way to properly protect them. In a previous article I demonstrated how to configure the Silverlight application to be downloaded over a standard unencrypted http connection whilst using https to communicate with the server. This option could be configured on the web service configuration, and I have written the code such that requests for reports will honour this setting too (ie. if SSL is to be used for WCF service calls then requests for reports will be made via https too).

On the client side (in the Silverlight application) I have created a ReportRequest class (under the Reporting namespace/folder) that simplifies requesting a report from the server. I have included a function to build the url to the report generation HTTP Handler (including adding the query string parameters for the report), and another to set the temporary user credentials cookies.

To demonstrate the solution I have incorporated two reports into the application. You’ll notice in the inventory section of the application that there is now a “Product Catalog Report” menu item in the side bar. This example demonstrates implementing the HTML Viewer control to display a report that appears to be contained within the Silverlight application. This report was not one that I designed myself but was one that I obtained from the SQL Server Reporting Services examples on CodePlex. As previously mentioned the templates built using the Visual Studio Report Designer and those for SQL Server Reporting Services both use the same RDL (Report Definition Language) file format, and can almost be used interchangeably. The primary difference we need to worry about is that the database query is contained within the report to be run under SQL Server Reporting Services, whereas using the local engine we need to pass the data for the report into the report viewer engine. RDL files are XML based, so I opened it up in Notepad and copied out the query. I created a class containing matching properties with the same field names included in the query in my web project, and then wrote a LINQ to Entities query to query my Entity Framework model, pull back the same data as the query in the report would, and populate a collection of my new class. I opened the report in the Report Designer and changed the data source to reference the collection of my class (which wasn’t really necessary). Now when generating the report I can set the populated collection as the data source for the report and it will render the report as it would have under SQL Server Reporting Services.

The other example demonstrates enabling the user to print the details of a product. As previously described, there is no printing functionality within Silverlight, so to implement this feature we can display a report that the user can then print – it’s not an ideal or elegant solution but does work. On the product details screen I have added a “Printable” button to the toolbar. I investigated automating the Adobe Acrobat plug-in to automatically print the document but I wasn’t particularly happy with the possible solutions so have decided to omit this functionality. Therefore the PDF won’t be directly sent to the printer, but instead relies on the report being downloaded and displayed with the user manually selecting the Print option from the Acrobat Reader plug-in. As an additional manual step is required in this process to start the printing process I decided to name the button “Printable” rather than “Print” to help save any confusion. Using a report to enable details printing functionality such as this means that extra work is involved in development to produce a report template (as opposed to printing a HTML page), but should result in a better looking output.

So that the product details screen isn’t closed when the user wants to print the details I decided to open the report in a new (popup) window rather than using the HTML Viewer control within the application. This is a simple process using the HTML Bridge – the HtmlPage.PopupWindow function will pop up a new window with the specified options (such as the size of the window, whether the menu bar or scroll bars should be shown, etc), and will navigate to the specified url. Note that as the report opens in a popup window, the user may have popup windows disabled and may need to add your site to the list of sites permitted to open popup windows in order for the report window to open. I have wrapped this functionality up in the OpenReportInNewWindow function in the new ReportRequest class.

Note that there is another issue to be aware of. The report is generated based upon the data in the database – not as it is currently displayed on the screen. Therefore the user will need to save their changes before clicking the Print button in order for them to appear in the report. Currently I don’t currently check to make sure that all changes have been saved before displaying the report – thus any unsaved changes to the product will not appear and may create some confusion for the user. The two solutions to this are to either save the product details before generating and displaying the report, or check to see if the user has any unsaved changes and request they save them first before generating the report. The second solution is probably the best but I have not implemented it as yet.

An issue worth mentioning (as it has created confusion for me on a number of occasions) is that the Adobe Acrobat Reader plug-in sometimes starts to fail to load leaving you with just a white screen where the report should be. What I have found is required is you to open up Task Manager and end the AcroRd32.exe process. Then attempt to view the report again and the plug-in will load correctly.

When deploying the application you’ll need to install the runtime for the report engine which isn’t installed as a part of the .NET Framework. If you don’t have the Microsoft Report Viewer Redistributable 2008, you can download it from here.

 

Alternative Solutions

There are many third party reporting tools available – most of which can export reports to PDF and be used in the same manner described in this article. If you have a preferred reporting tool then it should be fairly easy to substitute the one I have used with your own.

On my soapbox for just one minute, please don’t create your own reporting tool unless you really need to! I expect a good amount of disagreement and controversy on this point, but I don’t believe writing a custom reporting tool provides good value for money for clients, and can add a huge maintenance burden to an application. It may be a fun project to work on, but it creates maintenance and support nightmares as there is (in my opinion) no such thing as a perfect reporting tool. I sincerely believe custom reporting tools are a recipe for a black hole in your project budget and timeline. There are many reporting tool packages out there, and while none of them are perfect they will tend to satisfy most client requirements at a reasonable cost. On a similar point, I have found that creating report templates almost always gets pushed back to the developer no matter how easy the report builder might be to use or how tech savvy the user might be – users tend to have better things to do with their time than design reports, so I don’t personally believe it’s viable to push report template creation away from developers. I do see value in enabling the user to modify the output after generating a report however, as when minor tweaks are required they can add an excessive burden on the support team. That’s why I tend towards favouring an output that the users can edit to suit their needs such as generating Word documents rather than PDFs, and when using the Open XML standard (DOCX) format introduced in Microsoft Word 2007 (with the Office Compatibility Pack downloadable from Microsoft to open these files in earlier versions of Word) it can be very easy to populate a Word document template with data on the server (without requiring messy automation). This may sound like what I was advocating against (building your own reporting tool) and to some extent it is, so I don’t recommend it in all cases. In some cases it may be better to move to a reporting engine that can generate DOC or DOCX as their output (such as scaling up to SQL Server Reporting Services).

Conclusion

We now have implemented a means for displaying reports that appear to be within the application and permitting them to be printed. This solution has its faults and is lacking in elegance in some aspects, but is still a viable and workable solution. Stay tuned for my next article which will cover styling the application to give it a professional look.

Resources

Limitations of Windowless Mode for Silverlight by Karl Erickson:

http://blogs.msdn.com/silverlight_sdk/archive/2008/11/12/limitations-of-windowless-mode-for-silverlight.aspx

Displaying HTML using Silverlight 2:

http://blogs.msdn.com/markda/archive/2008/05/21/displaying-html-using-silverlight-2.aspx

Silverlight HTML Bridge FAQ by Erik Reitan:

http://blogs.msdn.com/erikreitan/archive/2008/12/02/silverlight-html-bridge-faq.aspx


Subscribe

Comments

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Matt Watson on Jan 05, 2009 20:29

    I can't wait for a SQL Reporting viewer for Silverlight.

    VinSolutions
    dealer website design

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Bob Thomson on Jan 07, 2009 15:55

    This is really helpful. We're building a Silverlight 2 collaboration application called:

    colaab.com

    Into which we need to introduce some reporting functionality for customer invoices and suchlike. I was considering Reporting Services reports and it's great to have such a detailed description of how to go about it.

    Thanks,

    Bob

    stormideas

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Andrus on Jan 10, 2009 10:59

    how to use open source http://fyireporting.com

    SilverLight report viewer and WinForms designer from this SL application ?

    In uses RDL format also.

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 11, 2009 09:24

    Hi Andrus

    As FYI Reporting produces RLDC reports you would use it exactly the same way as described but develop the report in the FYI Reporting designer.  You would not be able to use the designer within your Silverlight application as it is WinForms based.

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Jon on Jan 19, 2009 00:18

    Really good stuff - thanks for keeping up with it.  I am using your source as a framework for an app I'm trying to prove out with Silverlight.  I've deviated slightly by using some 3rd party controls to avoid some of the headache you encountered.  One of the issues that I'm finding is that when i'm using the grid to navigate to another page i'm getting some ugly errors.  I think this occurs because i'm responding to a grid event but then removing the UserControl parent.  This has happened with both the standard datagrid and a 3rd party grid.  I've even noticed it happens on the AGDatagGrid in  your app when clicking on an inventory item to update, though only rarely.  Have you encountered this issue yet?

    Thanks

    Jon

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 19, 2009 05:02

    Hi Jon

    Good to hear my framework has been of help to you - I'd love to see what you (or anyone else) produces based upon it.  Because it's open source I'm stuck to freely available controls but I think you've made a good move to use some third party controls to save some of the headaches I encountered,  Are you able to tell me what the error (plus stacktrace) is that you're receiving and if there is a set way to reproduce it with the online demo?  It could be the elusive bug I've seen on a couple of occasions but not been able to reproduce (which makes me think there could be something weird going on in the Silverlight runtime) and hasn't as yet been reported by anyone else.  Much like you say the app can suddenly throw an exception when changing a page.  I've just spent some time clicking around randomly trying to reproduce it without any luck.  What version of the framework are you using - is it this one where a new Closing event was implemented or before that?  I haven't seen this bug recently but would love to track it down as I'm not a fan of random bugs.  Let me know if you come up with something.  If anyone else has experienced this bug please let me know - I was hoping it was just something in the development/debugging process that was causing it.

    Thanks

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Jon on Jan 19, 2009 21:17

    I'm building this framework for a ticketing app.  When a pharmaceutical sales rep calls in with a IT related issue, say a laptop issue, this app is used by the level 1 call rep to track and route the problem.  Yes the Telerik controls are nice, albeit still not ripe.  The nice thing is they have constant releases and a really nice treeview control which is critical to my app since it supports a problem category taxonomy.  Not to mention, I avoided the combobox nightmare scenerio ; )

    The only thing I could find on the forums that make sense about this error seem to point to UI elements being disposed too quickly.  If I call the same code through a button click instead of a grid select event the problem does not happen.  Here is the forum post if interested (see last entry):

    http://silverlight.net/forums/t/18983.aspx

    I also posted on the forum and got some vague advice about using the Dispatcher.BeginInvoke but that didn't work.

    http://silverlight.net/forums/t/66413.aspx

    Here is the call:

    private void RadGridView_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangeEventArgs e)
            {

                customer = CustomerGrid.CurrentItem as CustomerBO.Customer;

                if (CustomerChange != null)
                    CustomerChange(this, new CustomerChangedArgs(customer));

                if (NavigateRequest != null && customer != null)
                    NavigateRequest(this, new NavigateRequestArgs(Globals.PAGE_CUSTOMER_PROFILE, null));
     
            }

     

    and the error:

    Unhandled Error in Silverlight 2 Application Value does not fall within the expected range. at MS.Internal.XcpImports.MethodEx(IntPtr ptr, String name, CValue[] cvData) at MS.Internal.XcpImports.MethodPack(IntPtr objectPtr, String methodName, Object[] rawData) at MS.Internal.XcpImports.UIElement_TransformToVisual(UIElement element, UIElement visual) at System.Windows.UIElement.TransformToVisual(UIElement visual) at Telerik.Windows.Controls.GridView.GridViewVirtualizingPanel.ScrollHorizontallyIfNeeded(UIElement visual) at Telerik.Windows.Controls.GridView.GridViewVirtualizingPanel.MakeVisible(UIElement visual, Rect rectangle) at Telerik.Windows.Controls.GridView.GridViewScrollViewer.HandleCellRequestForBringIntoView(UIElement focusedCell) at Telerik.Windows.Controls.GridView.GridViewScrollViewer.HandleRequestForBringIntoView(Object sender, RadRoutedEventArgs e) at Telerik.Windows.RadRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget) at Telerik.Windows.RadRoutedEventArgs.InvokeHandler(Delegate handler, Object target) at Telerik.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RadRoutedEventArgs routedEventArgs) at Telerik.Windows.RouteItem.InvokeHandler(RadRoutedEventArgs routedEventArgs) at Telerik.Windows.EventRoute.InvokeHandlersImpl(Object source, RadRoutedEventArgs args, Boolean raisedAgain) at Telerik.Windows.EventRoute.InvokeHandlers(Object source, RadRoutedEventArgs args) at Telerik.Windows.RadRoutedEventHelper.RaiseEvent(DependencyObject element, RadRoutedEventArgs args) at Telerik.Windows.DependencyObjectExtensions.RaiseEvent(DependencyObject element, RadRoutedEventArgs e) at Telerik.Windows.Controls.GridView.GridViewCell.OnGotFocus(RoutedEventArgs e) at System.Windows.Controls.Control.OnGotFocus(Control ctrl, EventArgs e) at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName)

     

    It doesn't actually cause too much grief, except the debugger gets hung up on the error and I can't proceed.  I think it might represent more of a design flaw on my part since I'm removing a page that has an "active" component.  But then why just the grid and not a combobox, for instance.  Anyway, I'll keep plugging on this since I can't come up with a work-around and let you know if i'm successful.

    Thanks

    Jon

     

     

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Jon on Jan 19, 2009 21:20

    Forgot to add:  I'm using the latest framework though I've added some modification to enable caching of those pages.  The problem though is with the removing of control from page.xaml which i have not modifed.

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 20, 2009 04:48

    Hi Jon

    Thanks for that.  This is a curly one!  It could be similar to the error I mentioned I'd seen a couple of times though I honestly can't remember exactly what it was as I haven't seen it recently (and hoped it had gone away).  I was hoping to use the stack trace you provided to narrow down the issue using Reflector but I don't think it will be much use.  The stack trace indicates that the Telerik DataGrid for some reason at that point is trying to do some calculations in order to work out how to draw itself, even though it should longer be displayed (which is likely to be the reason for the error).  Are you experiencing the exception randomly or is it easily reproduceable?  If so, what needs to be done is a simple cutdown sample application that reproduces the problem with some regularity and then it can be submitted as an issue to community members such as myself and possibly on to Telerik or Microsoft Connect if it is their issue.  My guess is that the cause of the randomness is that it might take a varying amount of time to hide the control on the form, or that the garbage collector sometimes kicks in quickly, and based upon the stack trace it's then trying to calculate something for the display of the grid, but being hidden or disposed it's an invalid calculation.  Very hacky, but maybe catch the Closing event on the "page" control and set the visibility of the DataGrid to hidden to possibly disable this calculation?  Pulling at straws but it could resolve the issue. Have you tried Telerik support?  Based upon the stack trace the exception is due to the Telerik control trying to calculate its visual aspects after it is hidden/disposed or an ancestor in the visual tree is hidden/disposed - they may be able to track it down for you.  If you have the source code for the DataGrid you might be able to link it in as a project and try to understand why the functions in the stack trace are being called which generate the exception.  Sorry I can't be of more help - I'm pretty much guessing at this point, but hope it might give you some ideas to work with.

    Regards

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Jon on Jan 25, 2009 17:10

    Chris - for the life of me I cannot figure out how you created the TargetControl property in the FieldValidator class.  More specifically, how does TargetControl setter know that it should set the property to the child control?  I cannot see anywhere that the TargetControl is explicitly set.  How are  you pulling off this magic? 

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 26, 2009 03:59

    Hi Jon

    I went back and looked at the previous article where I described the Validator control implementation and found that I didn't actually touch on this point ,so thanks for pointing it out - I'll need to do an update to that article.  If you don't know where to look when trying to follow the logic through it seems like it's happening by magic as you say :).  Essentially by making the data entry field control a "child" of the validator you are assigning its Content property.  I added the following attribute to the class in the code behind:

    [

    ContentProperty("TargetControl")]

    By doing this, a reference to the direct content of this user control (without requiring any intermediate properties) will be automatically assigned to the specified property (in this case a reference to the data entry field control).  It's an alternative to the user needing to write their markup with an intermediate property, so they can do something like this:

    <Validator ....><TextBox /></Validator>

    instead of:

    <Validator ....><Validator.TargetControl><TextBox /></Validator.TargetControl></Validator>

    Much cleaner from a XAML perspective, but trying to work it out without knowing the trick can make it a bit difficult to understand.  I intended on writing a bit about that (because it's not well documented if you do a Google search) but slipped my mind.  Hopefully I explained it well enough here - and at some stage I'll update the article to explain it a bit better.  Thanks for pointing out this omission.

    Did you manage to track down any more details about that error?

    Regards

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Jon on Jan 26, 2009 21:07

    Ah - so the key was the  ContentProperty("TargetControl")] attribute.  Setting that made the property "the" way to set the content.  Nice find.  Thats some nice code you worked up for the field validation.  You obviously know your stuff.  Makes me wonder why the MS team couldn't have come up with something similar already.

    At this point I'm quite certain that my bug is a Telerik problem.  I'm working with their beta datagrid and have been pointing out the problem, which they have been prompty responding to.  Only problem is that every time they fix one thing they break another.  Good news is that I don't think it affects the AGDataGrid or the standard grid.  I've finally managed to use that blacklight dashboard page to populate 4 datagrids that represent ticket queues.  Each grid is on a timer that asynchronously pulls data down from a WCF call and populates the grid on a specified interval.  Very cool bit of functionality that works with no flicker or disruption.  Here is a good article on how to do that...

    http://www.silverlightshow.net/items/Tip-Asynchronous-Silverlight-Execute-on-the-UI-thread.aspx

    So, do you plan on doing anything with unit testing?  We are about to kick off our project (officially) and are taking a TDD approach.  Not sure if you dabble in such things.

    Jon

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Sarah on Jan 27, 2009 03:48

    Chris,

    I am trying to add some LINQ to query the entity framework.  In the entity model I have a table project that is linked to another table PAN by projectID.  The mapping is defined and it is a one to many relationship (1 project has many PANs).

    IQueryable<ProjectsBO.PAN> qry = from p in context.Project.Include("PAN")
                                                     where p.projectID == ProjectID
                                                     select new ProjectsBO.PAN
                                                     {
                                                         projectID = p.projectID,
                                                         PANno = p.PAN.PANno,

    };
                    return qry.ToArray();

    but get the following error:

    Error    3    'System.Data.Objects.DataClasses.EntityCollection<CDWeb.PAN>' does not contain a definition for 'PANno' and no extension method 'PANno' accepting a first argument of type 'System.Data.Objects.DataClasses.EntityCollection<CDWeb.PAN>' could be found (are you missing a using directive or an assembly reference?)    C:\sandbox\CDWeb\CDWeb\CDDataService.svc.cs    770    68    CDWeb
     

    I have successfully done this with other tables in the database but they were also a struggle to get working and when they did I didn't know why they had succeeded.

     

    I also have added the following code to a form page:

            private void SaveProject()
            {
                if (PageStatusChange != null)
                    PageStatusChange(this, new PageStatusChangeArgs(PageStatusChangeArgs.eStatuses.RetrievingData));

                CDDataServiceClient service = CDServiceFactory.GetService();
                service.SaveBidAssessmentCompleted += new  EventHandler<SaveBidAssessmentCompletedEventArgs>(CDDataService_SaveBidAssessmentCompleted);
                service.SaveBidAssessmentAsync(m_currentBid);
            }


            private void CDDataService_SaveBidAssessmentCompleted(object sender, SaveBidAssessmentCompletedEventArgs e)
            {
                if (PageStatusChange != null)
                    PageStatusChange(this, new PageStatusChangeArgs(PageStatusChangeArgs.eStatuses.Active));

                if (e.Error != null)
                {
                    MessageBox.Show("An error occurred saving the bid assessment: " + e.Error.Message);
                }
                else
                {
                    // Update this product object with the new ID assigned
                    //m_projectID = e.Result;
                    m_currentBid.projectID = m_projectID;
                    DeleteButton.Enabled = true;
                }
            }

    and the compiler doesn't find a definition of SaveBidAssessmentCompletedEventArgs.  I have hacked the auto generated reference.cs file to add this definition but of course when you update the webservice this gets overwritten.

    Would you know what steps I am missing?  Many thanks, Sarah

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 27, 2009 09:57

    Hi Jon

    I hope you get the bug solved with the Telerik grid - let me know if you do.  Telerik seem to be very good with their support, and it's good to see they're working with you on this.  Good to see that you've been extending the project and filling in the dashboard - that's an article I have planned coming up.  Testing is another article I have plans for, but that's a little bit away at the moment as I've been sidetracked with work lately.  I have a whole raft of topics to talk about but due to the sheer amount of effort each one takes there is a bit of a delay between them at the moment.  I'm also very interested in what other people are wanting information on in building a business application so fire away with any topics you'd like me to cover.  Chances are they'll already be on my list but based upon demand I can reorder them a bit.

    Chris

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 27, 2009 10:03

    Hi Sarah

    Unfortunately it could be any number of things and it's a bit difficult to identify the issue without all the code.  In your select linq statement is the PAN entity and the PANno field coming up in your intellisense?  It's possible your entity model requires modification to ensure there is a relationship in your model.  Have you tried updating your model from the database?  The compiler won't find the args class if the WCF service isn't compiling (which it sounds as though it isn't.  Sorry I can't be of more help.

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Jon on Jan 27, 2009 12:25

    Chris - my 2 cents would be to prioritize the testing/unit testing framework only because TDD mandates that the testing happens early, not as an afterthought.  Of course, this is just a school of thought but it does seem to be the trend - at least here in the states.  Personally, I like silverlight because of the apparent ease in creating unit testing in compiled code vs javascript on the client.  That said anything we get from you is always much appreciated. 

    So - are you the only person in the whole world who knows how to create an end-to-end business app using silverlight  and not just bits and pieces?  Based on what I've seen and read I think so ; )

     

    Jon

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Sarah on Jan 28, 2009 03:30

    Chris,

    Thanks for your advice re entity model and args class.  Regarding topics of interest, your original plan of dashboard, administration and styling will be very useful and is a good development sequence.  In addition I am interested in workflow particularly authorising stages of a process.  So a user enters information into a form which then needs authorising before the process can continue.  There would need to be some routing in case the authoriser is absent and the form needs to be routed to another person.  In the Microsoft Health CUI demo it shows the user's email within the interface.  Are you able to demo how to view Exchange/Outlook messages within Silverlight?  A topic that I am struggling with is how to display multiple information parts on the same page (master/detail).  For instance one form I have lends it self to having a list box displaying the no of the form which when selected displays the form detail consisting of background information and the a two grids with details of invoices and budgets.  An example of using expanders or accordions would be useful or an alternative way of drilling down to the information.

    As Jon says above 'anything we get from you is always much appreciated.''  Thanks, Sarah.

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 28, 2009 10:16

    Hi Jon

    Thanks again for your input and I'll take it on board - proper testing is vital in developing robust software and deserves a thorough discussion as a part of this series.

    I don't think I'm the only person in the world who knows how to build an end-to-end business application, but I do believe I'm the only person writing extensively about the process.  This series was designed to fill that void, because I couldn't find (as you say) any more than just bits and pieces.  I have to say that along the way there have been many many hours of research and experiementation to get to this stage as many of the topics I discuss just aren't documented or discussed anywhere.  If they are, again as you say they are bits and pieces and not particularly thorough.  I guess I had a bit of a beef seeing demonstrations of "line of business applications" in Silverlight which were nothing of the sort - to me a business application is more than just calling a web service and displaying the results in a grid, and I feel the term is grossly misused in a lot of demonstrations and articles.  In addition important topics (including the "ComboBox nightmare") were totally ignored and you wouldn't know the problem existed until you hit it yourself.  Hopefully I've gone a bit of the way towards offsetting the imbalance by demonstrating real-world scenarios and solutions to the problems developers are going to experience.  There's still a lot more to cover, so stay tuned :).

    Chris

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 28, 2009 10:47

    Hi Sarah

    Thanks for your feedback.  Workflow is a very common element in line of business applications, and was on my list of topics though it hadn't been put assigned to a particular article as yet.  It will be coming up at some stage, so thanks for letting me know your interest in it.  Displaying Exchange emails might be an interesting topic, though I hadn't considered it up until now.  I'm probably unlikely to be covering that any time soon however I'm afraid due to the complexity of writing that so it could be used in a demonstration scenario, though if there is enough demand I might decide to do so.  Almost all business applications I've developed have had the concept of notes or messages that are added to the system when there has been a discussion with a client, a decision made, etc, which is a feature I did have on my list that might be similar to what you are after.  If you are looking to integrate directly with Exchange there are a number of possible solutions.  If you're using Exchange 2007 there is a new web service api that comes with it that might be best.  For previous versions you can use WebDAV to obtain data via an HTTP call.  Or you could just use CDO in your WCF service and return the results that way.  I'm not really a fan of master-detail type forms myself but I am likely to be demonstrating some sort of master-details implementation when I get to the Administration article purely because it is used quite often as a UI pattern.  Personally I don't find it to be very intuitive for users and prefer to display "detail" data in a popup or separate page.  That's just my preference though - but it does have its place so I will cover it anyway.  Expanders aren't a part of the standard controls in Silverlight, but there is an implementation in the Silverlight Toolkit that I plan to cover in the near future (probably in the Administration article).  Thanks for your feedback!

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Neil on Jan 29, 2009 07:37

    Great article and looks prefect for what I'm looking for. Though when I try and view your demo, I'm getting an invalid username & password when trying to login using demo & demo.

  • iiordanov

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by iiordanov on Jan 29, 2009 07:51

    Hi Neil,

    The demo account was locked because of multiple inputs of invalid usernames/passwords, but now it is unlocked again.

    Cheers

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Ken on Feb 02, 2009 12:05

    As of todat (02/02/2009) still getting an invalid username & password when trying to login using demo & demo.

    Cheers

     

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Jon on Feb 03, 2009 22:35

    Hi Chris,

    Just a thought about adding automated testing to your application.  I had an Agile/TDD team at my company review the app that I stole from you and modified for my proof-of-concept.  I wanted them to help me add unit testing, but it turns out that unless you start with tests first, it is very difficult to add them later.  As I'm starting to understand, making your app testable requires a certain design and the use of interfaces and abstractions that we usually wouldn't bother doing.  I was told it would be easier to redesign rather than retrofit with tests.  I might be telling you something you already know, but I just wanted to pass that on.

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Feb 04, 2009 12:09

    Hi Jon

    Thanks for your comments, and I can explain a few reasons why it's currently the way it is that doesn't make it completely testable as is.  To start with it would be best to use the M-V-VM pattern which you've probably seen mentioned around the place, as it structures the project more appropriately to implement testing.  When I wrote the first article it was my first attempt at writing a XAML based application and wasn't aware of that pattern as being the ideal pattern to use.  It's my plan to migrate to that pattern in the near future, which would be required before I can write an article on testing.  This is probably the greatest impediment in implementing testing, though I don't think it would be a lot of work to retrofit the application to use this pattern.  Things like the business objects should be reasonably easy to write tests for without major changes.  Possibly the complexity and major redesign issues that your team were describing would be to implement dependency injection and inversion of control to support the TDD process, which would require a certain amount of redesign.  Being an Agile/TDD team as you describe them I'm guessing this is what they are indicating.  When writing this series of articles I had to choose a line to walk between implementing enterprise hardcore design methodologies (which would just be too much to take in for many developers and remove the focus from solving the Silverlight specific issues I was targeting), or provide a simpler design that more developers could follow and use - which required sacrificing some higher end architecture principles and methodologies.  Since I was really focusing on Silverlight as the technology I did end up choosing the low road as such which wouldn't endear my project/framework sample to Agile/TDD purists.  I plan to introduce more solid methodologies as I go, which will require a certain amount of retrofitting, but then again you need to choose the right methodologies for the project (and not just using them for using them's sake), and not over-architecture the application (this may depend on the size/structure of your team and the size of the project).  I may end up having a couple of frameworks even, each targeting support for different methodologies.  So I see the framework as it is as a reasonably solid basis to work from, solving problems you will face however you structure your project and whatever methodologies you use, and you can go from that.  Definitely I'm not 100% happy with the framework currently and would like to move to a M-V-VM structure in the near future which will solve some of the testability issues.  This is an evolving project/framework and I welcome all feedback to improve it :).  If you have any other details or would like to discuss further you can go to the contact page on my blog (http://chrisa.wordpress.com/contact) and send me a private message.  Thanks for your feedback...

    Chris

  • -_-

    RE: Building a Silverlight LOB Part 6 - memory leak


    posted by Istvan on Feb 09, 2009 04:39

    Hello Cris!
     I love your article-series very much, thank you for it!
    Your approach is very attractive, and you  have settles in all chapter (almost :) ) just I need, and I have missed everywhere where I looked for.
    But, personally I would have prefer the explanation of  the code sometimes more deeply.

    Moreover  I'm afraid there is a memory leak! Every time one goes  to the detail page and back,  the IE memory-consumption grows up approx.  5 MB  in the demo site version  and the local version too.  Unfortunately I am quite newbie in .Net  programming, so I no have idea where  the problem is.

    Istvan

     

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Feb 15, 2009 09:44

    Hi Istvan

    Thanks for your feedback.  I see what you mean with the memory usage rising, but it's a bit confusing.  I'm not seeing the same effect when I look at the memory usage through Silverlight Spy which makes me think it's the browser holding onto objects not the Silverlight application.  There have been reports of memory leaks in the agDataGrid which may be the culprit - I need to update to the latest version which I'll probably do with the next article and see if that resolves the issue.

    Regards

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Istvan on Feb 20, 2009 11:15

    Hi Cris,

    Thanks the response!  I'm  eager to see the next version of  your AWLOB :) .

    Istvan 

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by David on Mar 02, 2009 04:33

    Hi Chris

    Great article and application! When is part 7 coming. I may have missed this in previous aticles but when I try an run your app and create an AdventureWorksEntitiesObject I get the following error "Keyword not supported: 'data source'." The database does exist and I have got the membership part working. I can only think that this error is masking some other error being thrown in the "EntityClient" provider.

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Chris Anderson on Mar 03, 2009 09:28

    Hi David

    I haven't come across this error, but my guess is that it's to do with the connection string you have in the web.config file (AdventureWorksEntities).  The connection strings are a bit different for use with the entity framework so make sure you're using the right connection string format.  If it is correct you should be able to open up the AdventureWorksModel.edmx file and update the model from the database with no issues.  Otherwise this is probably your problem.  Part 7 is very close and has been quite a bit of work - look out for it in the next week or so...

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Emma on Mar 05, 2009 10:07

    I can't tell you how invaluable these articles have been - thanks very much for all your time and effort, it's helped me out enormously!

    Emma

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by ecfreitas on Apr 08, 2009 17:02
    Great articles! I was hoping part 7 would already be available! Or the lauching of Silverlight 3.0 Beta have meddled with the original plan?
  • iiordanov

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by iiordanov on Apr 09, 2009 02:38
  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Bobby on Jul 09, 2009 14:11

    Hi can anyone give me solution for this . When i run application in my local system its throwing error

    Cannot open database "AdventureWorks" requested by the login. The login failed.
    Login failed for user ""

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Adam on Aug 17, 2009 18:16

    Chris,

    Thanks for the sample. You probably has been thanked enough. I just would like to add my voice to great job.

    I want to play with the dashboard. Do you have any sample or a link to sample good.

    Adam

     

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Aug 17, 2009 21:43
    Hi Adam

    I'm glad you've found the articles useful.  Unfortunately now that I've started writing a book I've been a little sidetracked from finishing my styling articles and moving on to look at things such as the dashboard.  Next month I'll be doing a presentation at TechEd Australia which I'll finish off the dashboard for.  It depends what you want to do anway, most of the structure is already in the project.  You just need to fill those panels - probably with graphs using something like the Silverlight Toolkit.  I don't know of any other good examples unfortunately except for those by third party control companies - you might want to look at Telerik, ComponentOne, Infragistics, and DevExpress - I think a couple of their sample applications include dashboards.  Hope this helps.

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Jesus Castrillo on Oct 13, 2009 16:41

    Hi Criss.

    I have a problem with a line in my app, traslate certanly topics of yoour app to my app, and result is this problem.

    Cannot implicitly convert type 'MyFirstApp.P2PServiceReference.TipoDictionaries' to 'MyFirstApp.Dictionaries.TipoDictionaries' 

    C:\Documents and Settings\jcastrillo\Escritorio\MyFirstApp\MainPage.xaml.cs 77 52 MyFirstApp

    this error is in event completed arguments, if you have any idea for this error, please... help me...

     

    Thk and Excellent Post

    Sorry for my english.

     

     

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Bryian Tan on Nov 19, 2009 04:54
    Hello, You have a Global.cs file with a static class and few properties like 

      public static string UserName = "";
            public static string Password = "";
            public static string[] UserRoles = null;
            public static bool IsLoggedIn = false;

    I'm new to Silverlight, I was wondering if the application will function accurately in a multiuser environment. Looking forward to hearing your feedback.

     

    Thanks,

    Bryian Tan

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Nov 19, 2009 14:04
    Hi Bryan

    Yes it's fine because Silverlight is run client side so this isn't an issue...

    Chris


  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Bryian Tan on Nov 19, 2009 19:25
    Chris,

    Thanks.

     

    Bryian Tan
  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Gary A on Mar 29, 2010 14:29
    The demo provided by your link doesn't work.  I get a WebExeption on the remote server.
  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Scott on Mar 29, 2010 22:00
    Can you guys check the app.  It appears to be down...
  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Peet on Dec 29, 2010 18:32

    Hey, love your article.

    The only bummer is that LocalReport (Microsoft.Reporting.WebForms) requires full trust, and our hosting server does not allow full trust.

    Do you know of any quick workarounds?

    Thanks,
    Peet

  • chrisanderson

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by chrisanderson on Jan 03, 2011 08:20

    Hi Peet

    I noticed that you posted this as a question on StackOverflow - it's probably best to continue the discussion there: http://stackoverflow.com/questions/4561922/localreport-webforms-and-partial-trust-for-pdf-generation.

    Chris

  • -_-

    RE: Building a Silverlight Line-Of-Business Application – Part 6


    posted by Matt on Apr 26, 2011 20:53
    I know you said that you prefer dealing with objects over DataSets, but for anyone that doesn't and/or you are interested in seeing some sample code for this in VB.NET you can check out this tutorial on XML DataSets with VB.NET.

Add Comment

Login to comment:
  *      *       

From this series