Building Line-of-Business Apps with Silverlight 2

"User experience" has never been a top concern when developing line-of-business apps, but Silverlight 2 might change that


September 03, 2008
URL:http://www.drdobbs.com/tools/building-line-of-business-apps-with-silv/210300284

Anthony Lombardo is the lead Technical Evangelist at Infragistics and recipient of the ASP.NET MVP Award from Microsoft. Tony co-runs the Central Jersey .NET Users Group.


Line-of-business applications have a notorious reputation for being all business and no pleasure. The fact is that "user experience" has never really been a top concern when developing line-of-business (LOB) applications. While many LOB-style applications are putting an increasing emphasis on usability, they often fall short on appeal. User experience is actually a combination of both usability and appeal, as in Figure 1.

Figure 1

LOB applications classically fall somewhere between "Please shoot me!", and "Day Job". But there's no reason they can't fall into the "First Love" category; a perfect mix of usability and appeal.

WPF has made it much easier for desktop applications to move into the "First Love" category of Figure 1, through its rich media capabilities, animation support, and declarative model. These same characteristics are driving differentiating experiences with Silverlight 2 as well, making "First Love" line-of-business apps for web client easier to build. There's no question that AJAX has fueled some of the richest Internet applications seen, but Silverlight promises to go even further. Silverlight not only makes creating rich user experiences easier, but also breaks through animation and media barriers where AJAX alone could not. But even beyond user experience, Silverlight's programmability alone gives it a leg up on the classic (and error prone) Javascript ways of the past. Understanding the advantages that Silverlight offers in the world of user experience is certainly important, but what's even more important is understanding how to perform classic line-of-business functions in this new framework. After all, the best user experience in the world isn't going to help an application that lacks required functionality.

Getting Started

The first thing to remember about a Silverlight application is that your code is running mainly on the client-side. This setup requires a solid communication layer connecting the client and the server, which is typically accomplished through web services; mainly WCF. Whether your databinding, authenticating, or even validating, you'll be talking through a web service at some point. Of course, you could use AJAX (XmlHTTPRequest) to communicate with the server; scripting the results to your Silverlight code, but that's best left to the hard core scripters out there.

Authentication

Any line-of-business application is going to have a requirement for some form of authentication. While Silverlight doesn't have authentication built into its core, you can easily re-use the ASP.NET authentication model.

Authentication for a Silverlight application is set up just like a typical ASP.NET application. Permissions can be set for pages and directories, using rules and roles through the web.config file. For most scenarios, Windows authentication will be used, for its tight integration between roles and ActiveDirectory. However, if you choose to use forms-based authentication, you'll need to add a way for the user to supply credentials to your application. This can be done through a typical ASP.NET login page which acts as the gateway to your application. However, if you're creating a full-screen Silverlight application, it's better to provide a login experience which more closely matches the rest of your application. Enter WCF once again.

ASP.NET 3.5 includes WCF services for Authentication, Roles, and Profiles. These services can easily be added to your application in a couple of steps. Because the service is already included in the .NET Framework, you simply need to create an endpoint for the service. The first step is to add the .svc file to your web site. You will want to add a plain text file in this case rather than using the "Silverlight Enabled WCF Service", since you don't actually need a code behind file. Listing One is an example of the AuthenticationService.


<%@ ServiceHost Language="C#" Debug="true" Service="System.Web.ApplicationServices.AuthenticationService" %>

Listing One

Aside from creating the service wrapper, you must also enable the service in the web.config file. This requires adding the service definition, bindings and behaviors as well as enabling the AuthenticationService through the system.web.extensions tag. Full details can be found in Listing Two.

<system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="authBinding">
                    <!-- Transport security is recommended -->
                    <security mode="Transport"/>
                </binding>
            </basicHttpBinding>
        </bindings>

        <behaviors>
            <serviceBehaviors>
                <behavior name="AuthenticationServiceTypeBehaviors">
                    <serviceMetadata httpGetEnabled="true"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

       <services>
            <service name="System.Web.ApplicationServices.AuthenticationService"
                           behaviorConfiguration="AuthenticationServiceTypeBehaviors">
                <endpoint contract="System.Web.ApplicationServices.AuthenticationService"
                          binding="basicHttpBinding" bindingConfiguration="authBinding"
                          bindingNamespace="http://asp.net/ApplicationServices/v200"/>
            </service>
        </services>
    </system.serviceModel>
    <system.web.extensions>
        <scripting>
          <webServices>
            <authenticationService enabled="true" requireSSL="false"/>
          </webServices>
        </scripting>
  </system.web.extensions>
Listing Two

With authentication, role and profile services all in place on your web site, you can now add the appropriate service references to your Silverlight application and get to work writing some code.

Application Settings and Storage

With authentication fresh in your minds, it's not a far stretch to start thinking about how to store user defined settings. In web applications, whether the user runs the application from their desktop, laptop, or even a co-worker's computer, user defined should always available. Silverlight applications should be no different. To preserve this idiom, personalization settings should be stored on the server rather than the client. Storing settings on the server is as easy as adding a service reference to the ProfileService. Just like in a classic ASP.NET application, the ProfileService can be used to save and load settings via a String Dictionary, as demonstrated in Listing Three. While server-side storage of user defined settings provides the user with a sort of "roaming profile", the disadvantage of using a server-side service is the latency associated with the request/response cycle. In most cases the additional wait time required should not be enough that it creates a negative experience. However, if you know that your application is going to be run on a slow network or over an intra-office VPN, you should think about caching a copy of the profile settings in IsolatedStorage.

ProfileServiceReference.ProfileServiceClient profileClient = new ProfileServiceReference.ProfileServiceClient();
  profileClient.GetPropertiesForCurrentUserCompleted += new EventHandler<Tracker.ProfileServiceReference.GetPropertiesForCurrentUserCompletedEventArgs>(profileClient_GetPropertiesForCurrentUserCompleted);
  profileClient.GetPropertiesForCurrentUserAsync(props, true);
void profileClient_GetPropertiesForCurrentUserCompleted(object sender, Tracker.ProfileServiceReference.GetPropertiesForCurrentUserCompletedEventArgs e)
{
  LoadSettingsDictionary(e.Result);
}
Listing Three

IsolatedStorage

Included with every Silverlight 2 application is a 100KB store that can be used to save settings on the client. The 100KB limit can be increased, but first requires approval from the end user. In most cases though, 100KB should be more than enough room to store settings. If you've worked with IsolatedStorage in WindowsForms applications, the code in Listing Four should look familiar as the API is almost identical. The main difference on the Silverlight side, is the additional requirements around space limits. Almost half of the code in Listing Four is dedicated to simply asserting space requirements, something that can easily be factored out and re-used. Once factored out, persisting items to IsolatedStorage is as simple as writing to a FileStream.

Aside from user defined settings, IsolatedStorage serves another key role. You've probably noticed by now that I used "cache" as my local variable name for the IsolatedStorageFile in Listing Four. In a client-centric application, reducing calls to the server and data transfers is the key to creating a usable, responsive application. IsolatedStorage is a perfect candidate for a client-side cache. Any time you're dealing with large lists of mainly static content, you should think about storing that content in IsolatedStorage. If your data maps directly to a database table, you can use a Timestamp column to determine whether your client-side cache is stale or not.

using (IsolatedStorageFile cache = IsolatedStorageFile.GetUserStoreForApplication())
{
    // Create our Settings object
    Settings settings = new Settings() { Size = new Point(1024, 768), ShowCloseConfirmDialog = true, Theme = "Blue" };
    
    // Use a StringBuilder/StringWriter combo since our desired
    // datatype is a string
    StringBuilder buffer=new StringBuilder();
    StringWriter writer =new StringWriter(buffer);

    // Serialize Settings object as a string
    XmlSerializer serializer = new XmlSerializer(typeof(Settings));
    serializer.Serialize(writer, settings);
    writer.Flush();
    writer.Close();

    // Get underlying string representation of Settings
    // and determine file size using Unicode encoding
    string serializedSettings = buffer.ToString();
    byte[] serializedSettingsBuffer = System.Text.Encoding.Unicode.GetBytes(serializedSettings);
    
    int maxSize = serializedSettingsBuffer.Length;
    Int64 availableSize = cache.AvailableFreeSpace;


    // IsolatedStorage limit is 100kb by default
    // but can be increased with the user's approval
    // check required size, and request increase if necessary
    if (maxSize > availableSize)
    {
        // Request additional space
        // If user denies request, we'll quit loading settings
        if (!cache.IncreaseQuotaTo(maxSize))
            return;
    }

    // Now that we have the string and enough space
    // we can write contents to IsolatedStorage
    using (IsolatedStorageFileStream storeFileStream = cache.OpenFile("Settings.xml", FileMode.OpenOrCreate, FileAccess.Write))
    {
        storeFileStream.Write(serializedSettingsBuffer,0,maxSize);
        // Don't need to close stream since we're scoped in the using block
    }
}
Listing Foure

Data Access

Describing a line-of-business application almost always results in mentioning a "grid". Displaying tabular data with the ability to sort, filter or otherwise augment the data is core to just about every LOB-style application. The Silverlght 2 toolbox is full of controls to get you started, including a DataGrid. Sliverlight DataBinding scenarios closely match that of WPF, so if you've already started getting up to speed on WPF you're a step ahead of the game. ASP.NET developers will also be used to the idea of Templates and declarative databinding. Setting up bindings can be done at an individual component level like you're used to with Windows Forms or ASP.NET, or you can set up a DataContext which will be inherited by all controls in a container. Using the DataContext will certainly be valuable in a line-of-business application, where textboxes and checkboxes representing the underlying data are ever present. Listing Five shows an example of a typical binding scenario, where the TextBox is bound to the Description field of the current DataContext. The DataContext in this case is set on the root element, the UserControl. The DataContext can simply be the entity business object retrieved via your WCF web service.


<TextBlock x:Name="labelSettings" Text="{Binding Description}"></TextBlock>

Listing Five

When binding the DataGrid, you'll be working with the ListSource property, which works much like the DataSource property of a classic .NET grid. How to bind the grid is not nearly as interesting as how to get the data in the first place though. Again you can turn to WCF, which provides the most straightforward means to transfer data between the server and the client. Once the communication channel is in place, your attention can turn to the actual data. For new applications which don't already have an underlying data model in place, using LinqToSql to generate dataclasses is worth a strong look. The trick to getting LinqToSql dataclasses to serialize through WCF is to set the DataContext's SerializationMode to Unidirectional, as in Figure 2. Setting the SerializationMode for the DataContext informs the code generator to decorate the classes and properties with the proper DataContract attributes. If you already have your middle tier business objects created you can certainly use those as well, but you'll want to mark those classes with the appropriate WCF DataContract attributes for proper serialization.

Figure 2

Along with the proper DataContract attributes, be sure that your business objects implement the INotifyPropertChanged interface to enable two-way databinding. In this case, two-way databinding means that data changes will be propagated to all consumers. For example, if you were to make changes to an underlying business object, the DataGrid bound to that business object would reflect those changes. Just as if you were to update the DataGrid, the business object would reflect the change as well. Remembering that Silvelright is client-centric, you still have to push data changes from the client to your back end server. The same web service you used to get your data to the client can be used to push changes back to the server. WCF simplifies this task, since pushing business objects over the wire is a trivial task.

A Note on Silverlight's DuplexService

The idea of a DuplexService in Silverlight is extremely attractive, as it enables data to be "pushed" from the server to the client. However, the underlying implementation is still dependant on HTTP connections, which do not enable server initiated communication. To get around this, Silverlight creates a polling system over an HTTP connection left open for a configurable amount of time. Because the entire polling model is neatly wrapped up and abstracted out in the DuplexService, the result is a service that feels like a server-side push. Unfortunately, this functionality is still not quite ready for prime time. The DuplexService is not part of the core Silverlight stack, and is provided in a separate evaluation assembly with its own special license for use. If you absolutely must have server push technology in your Silverlight application, this at least gives you something to work with, but for a typical application, its best to wait for this service to mature a little more before diving in.

Model View ViewModel (MVVM)

With an understanding of the internals of a Silverlight application, it's time to take a broader look at building a line-of-business application in this new environment. Application patterns have exploded in popularity lately. Take a look at what's going on with ASP.NET MVC as a prime example. Developers are looking for ways to make applications easier to work with, and especially easier to test.

You may have heard about Model-View-ViewModel (MVVM) already, as its quickly being adopted in the WPF world. MVVM is an application pattern geared towards improving the applications development and testing processes. The same reasons why MVVM is attractive to a WPF application, most notably the clear separation of design (XAML) from code, make it attractive for a Silverlight application. The goal of MVVM is to separate the design (View) from your underlying page logic (view-model), enabling designers to work completely with the XAML and developers to stay entirely in the code. Aside from being an easy pattern to follow and implement, it will pay dividends in testing and maintenance of your application. Even if you dont have a separate designer working on your XAML for you, this pattern is still worth a look at. It's easy to see why this pattern is becoming so popular so quick.

The MVVM story is a little bit different for Silverlight applications. Being a subset of WPF, silverlight doesnt contain everything that WPF does (as many WPF developers have found when trying to find Triggers in Silverlight...) The commanding framework in particular, is a core piece of the MVVM implementation for WPF, but is missing from the Silverlight subset. Since commands do not exist in Silverlight 2, a bit of custom code is required to glue the view (XAML) to the view-model. Luckily, this problem has already been solved, and the solution along with full source code can be downloaded and used in your project. For details, take a look at Nikhil Kothari's blog.

The Future of LOBs

The Silverlight 2 platform is powerful and familiar, yet different and strange at the same time. Learning to get used to the asynchronous model is something that will only come with experience. Combining rich-client concepts with web-client strategies is something that will take time to get used to. Building some of the richest Internet applications ever seen, is something that doesn't take much time to get used to at all. The topics covered in this article should give you a good idea of what the road ahead looks like. While it may be a new road that youve never traveled before, Silverlight programming is a combination familiar concepts and designs. The limitations fueling dreadful looking line-of-business applications are quickly disappearing. Many Silverlight demos focus on the appeal side of user experience through gratuitous use animations and video, but behind all of that glitz lives the framework for Line-of-Business 2.0.

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.