Category Archives: WCF

Silverlight 5: The Undisputed Champion for LOB Applications

In a previous post, I blogged about the struggles we’ve had with Silverlight that led me to consider WPF as an alternative for line of business applications. With the announcements made at today’s Silverlight Firestarter event about all the Silverlight 5 features, it seems like any incentive to make that switch to WPF has been eradicated. This post aims to take a look at some of those new features, and show how the gap is quickly closing between Silverlight 5 and WPF. Additionally, I’ll briefly dive into Silverlight’s exclusive features that ease development for LOB applications, yet are not present in WPF.

Performance!

Based on the Firestarter event, SL5 is cooking up even more improvements to the rendering pipeline that should alleviate scenarios where the visual tree gets overloaded. While exact details have yet to emerge, it seems that Silverlight will support an immediate graphics mode that will run rendering through the GPU. This was one of our largest blockers with Silverlight going forward, and it is a relief to hear that they have brought this WPF capability into the Silverlight realm.

DataBinding

If you’ve been working with Silverlight for awhile, you probably know that certain databinding scenarios can be a real pain. You probably also know that WPF has databinding facilities that solve these problems with ease. Well, the pain ends soon because Silverlight 5 now supports nearly all the features of it’s dying father, WPF.

One of my favorites is the Ancestor RelativeSource addition. As John Papa demonstrated in Firestarter today, there is a common scenario when performing bindings inside of a DataTemplate that don’t match your current DataContext. More often than not, you are forced to replicate properties/commands/collections on your child view models in order to satisfy your binding requirements, and often this can lead to redundant and confusing code. With Ancestor RelativeSource, you can find the DataContext of a parent element that is higher up in the visual tree hierarchy, and bind directly to it.

Another great feature is being able to bind to style setters. Often times there is a requirement to change visual properties of controls. But if you are trying to bind a style setter within Silverlight, it wasn’t possible without a heaping portion of hacky magic.

Finally, implicit data templates will make your annoying-converters-library much smaller. Often times when binding to a collection of dissimilar items, you are forced to use converters to get your data templates to render the intended layout. Of course, the more dissimilar your bound collection is, the more your library of one-off converters will grow. With implicit date templates, you have the option to bind to a list of different types, and let WPF dynamically determine which data template to use. This way your presentation logic can stay in xaml, and not in converter code.

Windows Integration

Another selling point for WPF is it’s ability to interactive with the windows environment from within your application, such as calling unmanaged libraries and Win32 APIs. A typical scenario is the process of exporting data to excel. In Silverlight right now, this workflow consists of the following steps:

  1. Prepare the xlsx filestream
  2. Offer the user SaveFileDialog to persist it to the local file system.
  3. The user types out an entire filename (since there is no way to specify a default in SL4)
  4. The user manually opens the file either from explorer/desktop or through excel

With Silverlight 5, you can skip the last three steps and open the file directly into Excel automatically! This is a huge time saver when your users constantly want to view their data in excel. And of course, there are so many more possibilities; in the Firestarter keynote, they demonstrated a Silverlight app that connected to a windows program to automatically import data off of a USB device. Rich OS integration used to be a major selling point for WPF, but with the advent of SL5, it has evaporated.

So far I’ve only touched on features that serve to even the playing field between Silverlight and WPF, but what puts SL5 over the top are the exclusive technologies and support that are actively being built around it:

  • WCF RIA Services – As I mentioned previously, there is no support in WPF for this great technology, and it isn’t coming anytime soon (if ever)
  • Fluid UI – Silverlight continues to build on the ability to easily create more natural applications. We see the beginnings of this with SL4′s ListBox support for Fluid UI, where you can effortlessly create transitions when adding and removing items. SL5 goes deeper and adds LoadTransitions. From the Firestarter event, this looks like the capabilities of the SL Toolkit’s TransitioningContentControl have been integrated into the VSM and animation system.
  • SL Toolkit – The state of WPF’s toolkit is a sad sad thing. With no release for the last 10 months (not even for the .NET 4 release), it looks to be nearly abandoned. Comparitively, there has been a .NET 4 release of the Silverlight toolkit, and it is much more feature complete and stable than it’s WPF counterpart.
  • Theming – This goes hand in hand with the previous bullet point, but there are a whole bunch of great themes continuing to be pumped out of Redmond. The WPF community has had to rely on rogue developers gracious enough to port the themes over.

Summary

There are many other improvements scheduled for Silverlight 5 that can help with LOB applications (Out of Browser, Testing tools, Text, Printing), but I’ll let the big dawgs like Scott Gu cover those details. For now, I think it’s safe to say that WPF is dead. But don’t fret; this just means that all of it’s most advantageous features are being reincarnated into future versions of Silverlight.

After last months scare that Microsoft might abandon Silverlight, I think it is safe to say that speculation could not be further from the truth; Silverlight is here to stay. It continues to get faster, leaner, stronger — and there is no better technology in the present or foreseable future that can be used to develop amazing line of business applications. With Silverlight 5′s release next summer and the beta still a few months out, there are going to be a swarm of developers clamoring to get their paws on these features (myself included). Until then, happy coding :)

WPF 4 vs. Silverlight 4: Which Do You Choose?

For the past year, I have led an initiative at my company to use Silverlight 4 and WCF RIA Services on the majority of our user interface projects. While these projects have been largely successful, we began running into serious performance problems when trying to squeeze large amounts of data onto our views. The problem wasn’t fetching the data, but rather scrolling and viewing the data in our DataGrids.

One of the largest optimizations we made was to set the windowless parameter back to false. But the root cause pointed to an overload of the Silverlight visual tree. Simply put, there’s only so much you can show on the screen at once, even with virtualization turned on. With a giant excel-like editable datagrid that sprawls the screen, there’s no getting around visual tree overload (especially when scrolling). We evaluated every commercial SL datagrid on the market, and chose the default SDK DataGrid from MS because it fared really well in our scenario.

In the end, we performed many optimizations to get the product to “acceptable” performance, but this motivated me to begin researching WPF as an alternative. I did a massive comparison of all the different WPF/Silverlight datagrids, and one theme remained the same: WPF has much more visual rendering power than Silverlight. These findings have made me dead-set on trying my best to see if WPF can be the platform-of-choice for major apps going forward, but it turns out that the performance honeymoon was short lived.

As I began to build a prototype in WPF, the giant glaring gaps quickly began to emerge. The first was that WPF doesn’t support RIA Services. This is a huge negative, and unless I find a hack to somehow get a client support for WPF, it will force us back to silverlight. The second big one was the validation story. Notice those “free” beautifully animated popout error messages in the datagrid and dataform controls in Silverlight? These are nowhere to be found in WPF. I have yet to find anyone who has replicated them in WPF, and I haven’t had time to try myself. Also, WPF does not have INotifyDataErrorInfo, so any async validation is going to be far less elegant.

And that isn’t the end. There are other smaller issues that deter me. For instance, WPF does not have Fluid UI like SL4, so there is no clean approach to adding natural animations to your data collections. I was hopeful that Blend’s FluidMoveBehavior would fill the gap, but I haven’t been able to get it working even in the most simple scenarios. Also, the WPF toolkit is in a sad state right now, with no updates since 9 months ago (aside from the Ribbon control). Silverlight is definitely getting more attention in this arena.

I really want to harness the power of WPF, but at this point it feels like Silverlight makes it much easier of an experience for developing LOB applications. With that said, I am still going to forge ahead and give my best shot at trying to make WPF work. But if I had to make a recommendation now, I would say that developers in similar circumstances should go for Silverlight first, while always keeping a hawk’s eye on performance. If your application isn’t doing a ton of CRUD on a remote data source, and thus validation and RIA Services aren’t necessary, then WPF becomes an easier sell.

In the event that I do make some breakthroughs with WPF, I’ll be sure to update this post. Stay tuned…

Working with Projections and DTOs in WCF Data Services

For those of you who haven’t been following “Project Astoria”, you’ve been missing out on some pretty exciting technology. WCF Data Services (formerly known as ADO.NET Data Services) is a stack on top of WCF that enables the creation and consumption of REST-based data services for the web. There are several intriguing features in the upcoming release that coincides with .NET Framework 4, including:

  • Projections: Since CTP2, the Data Services URI API supports the ability to work with a subset of properties on an Entity.
  • Data Binding: The client library now supports two-way data binding for applications built with Silverlight or WPF technologies.
  • Row Count: You can now retrieve the total number of entities in a set, without having to fetch all of the entities within that set.

The ability to create projections and shape your data directly on the URL can be quite useful. Oftentimes, only a few properties of an entity are necessary, and WCF Data Services makes it easy to achieve an efficient query that returns precisely the data you need. For an example, take the following Entity Framework data model:

Example Entity Model

Let’s say you only wanted to return a list of Employee Names, along with the City they live in. If exposed via a WCF Data Service, you could could get exactly this data by using the $select parameter in your querystring:

http://domain/data.svc/Employees?$select=Id,FirstName,LastName,Address/Id,Address/City&$expand=Address

This request will only return the Employee’s Id, FirstName, and LastName and the Address’s Id, and City. The $expand query parameter with the Address value is telling the service to eager load the Address object, which is necessary be able to return the projected properties that we need from it. Any developer who has been creating AJAX-intensive websites will tell you that ability to achieve this granularity without any extra work is extremely useful.

More Complex Scenarios

The projections and expansion features are extremely useful, but at some point you will undoubtedly run into a scenario that isn’t supported via the querystring API. WCF Data Services allows you to expose custom operations on your service to facilitate these scenarios. Using example data model above, let’s say we would want the Employee’s Id, Name, and the Count of the OptionsApprovals from the StockOptionApproval relationship. Since there is currently no way to project the count of a child relationship in the querytstring API (don’t misunderstand the $count parameter as I first did; it will not help here), you would need to expose a custom service operation. Intuitively, you might code something like this:
[csharp]
[WebGet]
public IEnumerable<EmployeeOptionApprovalCountDTO> EmployeesWithOptionApprovalCount()
{
var employees = CurrentDataSource.Employees
.Select(x => new EmployeeOptionApprovalCountDTO {
x.ID,
x.Name,
OptionsApprovalCount = x.Children.Count()
})
.ToList();

return employees;
}
[/csharp]

Unfortunately, this will not work. At least not when your WCFService inherits from an Entity Framework ObjectContext:
[csharp]
public class EmployeeService : DataService<EntityContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.UseVerboseErrors = true;
// more config options here…
}
}
[/csharp]

When your service inherits from an ObjectContext, WCF Data Services will use the ObjectContextDataProvider. A current limitation is that you can only return entities from the custom service operations that you expose. In other words, if you try to return a data transfer object (regular CLR class), your service will fault with:

'Unable to load metadata for return type 'System.Collections.Generic.IEnumerable`1[EmployeeOptionApprovalCountDTO]' of method 'System.Collections.Generic.IEnumerable`1[EmployeeOptionApprovalCountDTO] GetEntityWithCount(Int32)'

Disappointingly, you can’t even use the config’s RegisterKnownType method during InitializeService, because it isn’t used when ObjectContextDataProvider is chosen as the Provider for your service. So what other options do you have for this seemingly straightforward use case?

The next thing I tried was to create an Entity in the model that isn’t mapped to a table in the database. This was a dead end, because when using the unmapped entity in the entity data model as the DTO to return from the service, I received this exception:

The server encountered an error processing the request. The exception message is 'Service operation 'UnmappedEntityDTO' produces instances of type 'UnmappedEntityDTO', but there are no visible entity sets for that type. The service operation should be hidden or a resource set for type 'UnmappedEntityDTO' should be made visible.'.

So what are we left with to try? Fortunately, the entity framework has the concept of complex types, which technically are to be used as properties of entities. However, the ObjectContextDataProvider will allow you to return a complex type in the EntityDataModel from your service operation. You can create them in the Model Browser:

example-ef-complex-type

As if jumping through all those hoops weren’t enough, there is one more gotcha to consider. When building a Linq to Entities query, you cannot use a complex type as part of your where clause! You will receive the following exception:

The entity or complex type 'ComplexTypeAsDTO' cannot be constructed in a LINQ to Entities query.

So instead, you must first use an anonymous type, invoke ToList() to ensure your query gets executed, and then finally transform your anonymous type to your complex type so that your service is able to return your objects:
[csharp]
return CurrentDataSource.Employees
.Select(x => new{
Id = x.Id,
Name = x.Name,
OptionsApprovalCount = x.OptionsApprovals.Count
})
.ToList()
.Select(x => new EmployeeWithOptionsApprovalCount {
Id = x.Id,
Name = x.Name,
OptionsApprovalCount = x.OptionsApprovalCount
});
[/csharp]

Summary

WCF Data Services enables rapid development and the ability to easily expose your entity model. And when combined with the entity framework in conjunction with it’s new POCO support, you don’t have to sacrifice your n-tier architecture and proper separation of concerns. However, there are still some counterintuitive practices that must be used in order to handle seemingly-basic scenarios. Hopefully, by the time the final product is delivered, there will be better support for these situations. But for now, I’m happy that I found a decent workaround!