Note: This article is submitted by Chris Anderson for Silverlight: Write and Win contest. Thanks a lot, Chris! Hello All, Please drop a comment if you like it.
“It is time to vote now! Please, choose your favorite articles and enter your vote by going to contest page. Thank you!„
This article is compatible with the latest version of Silverlight.
Be sure to check all articles of the series: Part 1, Part 2, Part 3, Part 4, Part 5 and Part 6
Introduction
Silverlight is one of the major new technologies from Microsoft and will potentially have a huge impact on the Microsoft development community. Developers are rapidly looking to Silverlight to solve major challenges and limitations as posed by existing technologies (such as Windows Forms and ASP.NET). WPF uptake has been lukewarm at best, however the similarities it has with Silverlight could very well give it the kick it needs.
The problems is, if you have read any articles or been to any user group presentations for Silverlight you no doubt have noticed the number of what I like to call “fluff examples” (deep zoom, media players, animations) that don’t help much when you need to investigate the potential for Silverlight in your business. When I first started playing with Silverlight I felt quite lost as even though I’m an experienced application developer with Microsoft technologies, it is quite different to anything I’ve done before (I have not previously worked with WPF). When you first create a Windows Forms application and add a few controls you have something that looks like an application. However, the problem (psychological leap) with SL (and also WPF) is that when you first start a project add a few controls it still looks nothing like an application as such. No doubt if you’ve tried playing with Silverlight, as a developer you’ve faced the same confusion as I have. Attempting to get a LOB application up and running, there wasn’t a lot of information in the one place or similarly focused applications to get me started, requiring me to do a lot of research and develop from scratch. This article aims at walking you through the process to save you the same pain I have experienced.
I guess the big question is what makes Silverlight a good LOB platform, and why should we develop LOB applications using it? Comparable platforms as provided by the available Microsoft tools suitable for developing LOB applications include Windows Forms / WPF, web (ASP.NET webforms), and Microsoft Office based applications, each with their own advantages and disadvantages as described below.
Downsides of Windows Forms and WPF based applications include their reliance on Microsoft Windows as the operating system, deployment issues (requirement of large .NET Framework to be installed, administrative privileges required, etc), and distribution of software updates. The Click-Once technology reduces some of the deployment issues, but in comparison with other platforms it is still a lot more complicated to perform. Advantages of these platforms though include a rich user interface, full access to system resources, and the ability to interact with other installed applications such as Microsoft Office).
Microsoft Office based applications have a reliance on Microsoft Office (obviously), and if a .NET based (VSTO) solution then you'll also require the pre-installation of the .NET Framework. Thus like Windows Forms it incurs deployment issues, though advantages include the tight integration with the Office suite and all the features that provides.
Web based solutions mitigate the deployment issues of the above platforms and are not reliant on a particular platform for the clients to run (some solutions excepted).
Silverlight combines the power of a rich user interface / client with the deployment advantages of being deployed via the web and viewed via a browser. Unlike standard web applications, it will render the same on each platform despite the browser being used (cross browser rendering being the bane of web developers the world over). It is cross platform and cross browser, and thus holds great potential for developing applications across multiple operating systems and accessible via different web browsers.
What I would like to demonstrate in this article is Silverlight's potential as a Line Of Business (LOB) platform. I am currently writing an article on the structure of Line Of Business applications, and this application when completed will essentially accompany that article as a practical implementation of a LOB application in Silverlight.
Now to our solution. This article will provide an example of a LOB application based upon the AdventureWorks company often used in Microsoft sample applications, and will use the Microsoft SQL Server demonstration database as provided by Microsoft. Based upon time constraints, it will not be a complete end-to-end solution, but will provide a strong example of the possibilities gained using Silverlight as a development platform, and provide a strong foundation from which you can build your own LOB applications. AdventureWorks is a retail company that sells bicycles and associated accessories. A LOB application for AdventureWorks would allow them to manage their inventory, purchases from their suppliers, and sales to their customers. For the purpose of this article we will only look at the inventory management in the application.
Some aspects of developing the application will not be described in detail where information abounds on the internet - I will attempt to focus just on the aspects of developing a LOB application in Silverlight.
Source Code and Live Demo*
*To login in the sample application use the following Username: demo and Password: demo.
Prerequisites
To get started with a Silverlight application, go to http://www.silverlight.net/ and click on the Getting Started button. This will give you a list of the components you require to get started. In order to run the sample application you will also need a copy of the AdventureWorks sample database (search for it on CodePlex).
Using the Sample Application
This article comes with a sample application for our LOB application framework. Note that this application is by no means complete (essentially in beta version, but then so is Silverlight), but demonstrates how a LOB application could be implemented in Silverlight, and you could use this as a basis for your own applications.
To get started, unzip the package and load the solution in Visual Studio. Open the web.config file in the web application (AWWeb) as you will need to make a few adjustments for your system. Find the connectionStrings section, and change the connection strings for both elements to point towards your own AdventureWorks database instance. Unfortunately the SQL Server membership won’t accept the same connection string as the entity framework, thus two connection strings are required for the same database.
The AdventureWorks database doesn’t have the ASP.NET membership tables included, so we’ll need to add those and configure our security settings.
Using the Command Line / Run in the Start Menu, run:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe
Point it towards your AdventureWorks database and it will create the required tables, views, and stored procedures. Then using the ASP.NET Configuration tool for the web application (the right-most icon in the Solution Explorer window), set up users and roles for the application. You’ll need these to log into the system.
Application Structure
Our application will be structured in a similar manner to a client-server application, where the Silverlight portion of the system acts as our client, and the web application acts as our server. All access to data from the application will be via a WCF service, which will also verify security access to data and implement business rules. Access to the database will be via the new Entity Framework. Taking advantage of the rich client, some business rules (such as validation, workflow, etc) will be implemented on the client, but also implemented on the server to verify correct data access.
Creating and Configuring the Visual Studio Projects
So let's create our solution in Visual Studio, with the projects designed to support our application structure determined above. The server needs to serve up to the client the Silverlight application, and data between itself and the Silverlight application. My initial plan was to have two projects for the server components - one to serve up the Silverlight application (a standard web application project), and one to serve up data (a WCF Service project). There are a number of issues involved in this structure (such as cross domain communication issues as a security feature of Silverlight), and while this can be circumvented (implementing a cross domain policy file, or using IIS to host your projects instead of the personal web server default), ultimately you could conceptually join the two together to provide a single “server” project (the web application also hosting the WCF services).
Create a new project in Visual Studio, and select to create a Silverlight Application. Select to add a new web to the solution to host the Silverlight control. Add a new item to the web application project and select WCF Service. Our service will be named AWDataService.
Open up the web.config in the web application and make the following changes:
- Change includeExceptionDetailInFaults="false" to true so we can easily resolve WCF service exceptions. You should change this back when deploying your application.
- Change <compilation debug="false"> to true.
- Find the behaviour configuration for the WCF service, and change the binding from binding="wsHttpBinding" to basicHttpBinding (required for Silverlight to be able to communicate with this service).
- Add <serviceHostingEnvironment aspNetCompatibilityEnabled="false" /> in the <system.serviceModel> section.
Other changes to make to the web application include:
- Add a reference to the System.Service.Model DLL.
- Delete Default.aspx and the .htm test page (not required).
- Rename the .aspx test page (note to set it as your start page again afterwards)
- Open the .aspx page and change the page title.
Now let’s run the application. Hopefully it should start fine, and you will be presented with a blank page and the scroll bar on the side (in IE). Let’s get rid of this scroll bar as it detracts from the application and isn't required. Add the following code to the style attribute of the html tag in your aspx page:
style="overflow: hidden;"
Visual Studio may complain about this being invalid markup, but IE doesn’t keep to standards so we need to work with what we get. When you run the application again the scroll bar will be gone and you'll have a pure blank white canvas to work with. Not very interesting as it is, but we now have a base to work from.
Master Page / Look and Feel / Page Structure
When you first create a Silverlight project, you initially get just App.xaml and Page.xaml as your xaml files. Looking closer at both of these closer you will note that they are both of type UserControl. Initially I was stumped wondering how you created new “pages”, but every xaml file is actually a user control, and thus our content “pages” will also be user controls. We need to work from this basis to create an application. App.xaml will have our global resource definitions and control styles, and we will treat Page.xaml essentially as our Master Page (as you would find in an ASP.NET project, where the content “pages” are dynamically inserted into the output).
To provide a master page like structure, I have segmented the screen area (as hosted by Page.xaml) into three main areas - the header, the content, and the footer which will form our presentation framework. This is a common user interface structure for LOB web applications, and we’ll do much the same here. We’ll split up the available screen real estate into these three areas using a Grid control, and the header and the footer will each be their own user controls inserted into cells within the grid. The content will be dynamically inserted into the centre grid cell when requested by the code-behind.
The content page to be displayed will be loaded by the code behind upon requests that may emanate from any element (ie, the header, the footer, or a content page). To support this, the Page class will contain the page routing logic. Each element exposes a NavigateRequest event that Page.xaml responds to, unloading the current page control and loading the newly requested page. For example, clicking one of the toolbar buttons will be captured in the header control, which it then raises a NavigateRequest event to be handled by Page.xaml.
The rest of the application can respond to changes in the status of the current page as each page also implements the PageStatusChange event. Content pages often have to communicate with the server, and while it is doing this it is good to notify the user what is happening. In the footer control is a display indicator which monitors the PageStatusChange event raised by the content page, and displays a message while is has the RetrievingData status.
In order to maintain consistency and the ability to refer to pages in a generic manner, all content pages implement the IContentPage interface. This defines the required events that all content pages should raise so the Page class can respond accordingly.
The Header control contains a toolbar which I created as a custom control. The toolbar control contains a StackPanel, and it’s children are exposed as a public property of the control (in the code behind). To populate the toolbar, ToobarButton controls (also custom controls created for use in the toolbar) are added to this children collection. The ToolbarButton control contains a text block and a shape which is given some opacity when the mouse is over the control’s area to show it can be pressed. Note that the Toolbar control is reused for the sidebar.
My original design included a Full Screen button in the header that put the application into full screen mode (obviously). Much to my disappointment though, when Silverlight is put into full screen mode most keys on the keyboard are disabled (except Escape and the arrow keys). In a LOB application this was not particularly useful so I removed this option from the framework. Keyboard access is disabled for security purposes – hopefully in the release version an option is added to Silverlight to opt into permitting keyboard input in full screen mode.
The Login Page
The login page is the first content page to be loaded into the content area. Note that the password textbox doesn’t hide the entered text as is usually expected of a password entry field. The core Silverlight control library doesn’t contain a password text box, though various people have created their own and made them available for free. However the full release version of Silverlight will have a password text box, thus I have chosen not to include a custom solution as an official one will be soon available.
After being authenticated, these user credentials will be cached (in the Globals class) and will be sent with each call to the WCF service to authenticate operations on the data.
The Dashboard
Most good LOB applications provide a dashboard, which brings various areas of the application together in one screen with important data that displays the state of the business (or the world of that user’s responsibilities within that business) for the current user at a glance. I have not implemented a whole dashboard in this sample application but just the framework within which the elements of a dashboard could be placed. To help me with this I used the excellent controls from the open source Blacklight project (available from CodePlex) from which the DragDropPanelHost control provides a nice framework for a dashboard (try maximising and moving around the various panels). This requires a reference to be added to the Blacklight DLL and then the provided DragDropPanelHost control can be used in the page. I have added my own styling to the DragDropPanelHost control to look like a dashboard, which I have located in the App.xaml file.
Panels within the dashboard can be moved around and a future addition to the screen would be the ability to save the state of these panels, which is not currently implemented in my sample application.
List/Search Screens
The List/Search screen allows us to find a particular item in the system and drill down upon it. To view the summary items we will use the DataGrid control. To use this you will need to add a reference to your project for System.Windows.Controls.Data. The DataGrid control is quite large, so you will see a noticeable increase in the size of your .xap file. The DataGrid has a lot of shortcomings (especially in this scenario because it is designed for inline editing which we don’t want) and is by no means perfect. DevExpress has an open source DataGrid control (which also supports grouping, not supported by the standard DataGrid) which you may wish to consider as a replacement grid. However I will use the standard DataGrid for the purpose of this sample. The styling of the standard DataGrid is not particularly attractive, so I have used a style found in a Silverlight forum (see references for link). The styling has been put into the App.xaml so it can be used from multiple controls in the project. There are still a number of styling issues which hopefully will be fixed (such as the white area in the top left of the grid that appears when hiding the row headers, ie. setting HeadersVisibility="Column") when Silverlight is released.
Things that you would want to be able to do in a list screen such as this would be to page the data, group the rows (such as by category), and sort the rows. Of these, the standard DataGrid only supports sorting. As returning too many rows causes the WCF service to throw an exception (due to data message limit) I return only the top 100 rows of results. Implementing paging is required in this scenario, however this is not currently implemented in the sample application but will come in the next release.
Note that the Sidebar to this screen is actually our Toolbar control with some different properties applied to change how it operates. Therefore the Toolbar control performs dual duties, acting as a multi-purpose control.
The search allows you to find a particular item quickly – in the case of the sample application it is searching for items whose product name contains the search text. Clicking Search will query the server for the results.
To drill down on a particular item, click the product name hyperlink for that item in the list. Originally my concept was to be able to click anywhere on the row to drill down on an item, however this wasn’t possible in the standard DataGrid. Instead I needed to specify the Product Name column to be a DataGridTemplateColumn, which contained a HyperlinkButton that was bound to our data. When a product hyperlink is clicked we capture that event and the ID of the associated product and raise the NavigateRequest event so that the Page class will unload the list screen and load the details screen with the details of that product.
One other item of note is the List Price column in the Inventory List screen. The ListPrice property is being bound to is a decimal, yet we want to display it as a currency (starting with a dollar sign, and to two decimal places not four). To do this we needed to provide a converter class in the binding to format the value as a string. I created a class called CurrencyConverter which implements the IValueConverter interface for this purpose. So that the value is formatted we need to reference the converter namespace:
xmlns:converters="clr-namespace:SilverlightLOBFramework.ValueConverters"
Reference the converter(s) to be used in our UserResources:
<UserControl.Resources>
<converters:CurrencyConverter x:Key="currencyConverter" />
</UserControl.Resources>
And then reference the converter in our binding:
DisplayMemberBinding="{Binding ListPrice, Converter={StaticResource currencyConverter}}"
Edit Details Screens
Unfortunately due to time constraints the edit details screens have not been implemented. This will be coming in the near future.
Designing The WCF Data Service
There were a number of ways of communicating with the server to obtain/modify data. I originally investigated ADO.NET Data Services (previously code named Astoria), but found that they probably would not meet my needs. I intend to investigate them further, but in the meantime I have chosen to manually implement a standard WCF service. As there are numerous sources about using WCF services from Silverlight I will not go into depth on this topic here.
Note each time we create an instance of the WCF service we pass through the URL of the web service so we use the correct server address (not hardcoded to a single URL). A static property is defined in the Globals class that determines (based upon the URL that the Silverlight application was loaded from) what the correct URL of the WCF service should be. This allows the application to be easily deployed between a development machine and multiple server deployments.
When making any call to the WCF service we need to pass our user credentials to ensure that only data that the user has permission to view/edit and perform actions upon is permitted, and validated back at the server. This is vital for security purposes. Currently this is not implemented in the sample application but will be in the next version.
Returning data to the client we pass the data through as Data Transfer Objects (DTOs). These are lightweight classes used purely for passing data between the server and the client. We populate these classes with data from the Entity Framework queries.
Note there is a limit to the message size when communicating with a WCF service. Retrieving too much data in a single call may result in a message size exceeded exception. Whilst this limit can be modified via configuration it is best to design your calls accordingly and only pass small amounts of data at one time (eg. Paging results in a list, etc). This is an aspect that needs to be considered when designing your WCF service.
Exception handling (if web server inaccessible, etc) is an issue that has not been properly implemented in the current version of the sample application, but will come in the next version.
Future
Some of the changes that will be coming in the near future to the application framework will include:
- Dynamic Content Loading – so the entire application doesn’t need to be downloaded it should be split into smaller sections that can be downloaded only when the user wants them.
- Caching data locally – so data that rarely changes doesn’t need to be retrieved from the server each time it is required.
- Business Logic – a better way for handling business logic
- Include support for unit testing
- Include support for versioning the application
- Include support for exception logging
- Implement WCF service authentication
Conclusion
I guess the big question this article attempted to answer was is Silverlight suitable as a Line-Of-Business platform. As you can see, it took quite a bit of work to get a basic application up and running, but I firmly believe that the potential Silverlight provides outweighs the initial development heartaches.
With the full release of Silverlight coming soon and resolving some of the issues and adding to the core control set, things will become a little easier. With the various commercial control libraries that are coming available (Netikatech, Telerik, ComponentOne, Infragistics, DevExpress, Vectorlight, etc) most of your LOB application control needs should be covered.
The sample application is by no means complete, and still requires some important structural elements to be added (such as business logic, exception logging, unit tests, etc). However this is just an initial version (alpha/beta if you will) for feedback - work will continue and a complete version will be available in the near future. At the point that the framework is complete I will release it as a Visual Studio template to enable you to get a Silverlight LOB application up and running easily by simply creating a new project in Visual Studio. In the meantime it will provide a good foundation from which you can study Silverlight and prototype your own line-of-business applications.
References
Blacklight: http://www.codeplex.com/blacklight
Datagrid styling link: http://silverlight.net/forums/t/12518.aspx