Jonas Follesø profile picture

Jonas Follesø

Software Developer

Sharing logic between server and client

August 8th 2008

When building line-of-business (Smart Clients or Rich Internet Applications) you normally talk to some back-end web service responsible for enforcing business rules, authentication, and storing your data in some database. When implementing your client application you often end up re-implementing some of these business rules to give the user a better experience. Instead of having to pass an Order-object to the web service just to get an exception saying that the order date field is a required, you should try to enforce these validation rules directly in your user interface. How do you best implement these rules across your tiers?

Sharing is caring!

In his January 2004 MSDN article title "A Guide to Developing and Running Connected Systems with Indigo" Don Box presented four rules for connected systems, later often referred to as “the four tenets of SOA”. The rules are as following:

  • Boundaries are explicit
  • Services are autonomous
  • Services share schema and contract, not class
  • Service compatibility is determined based on policy

Especially rule number three is relevant when talking about implementing business rules on both server and client. In traditional object oriented design you would implement your domain- or business objects and let them encapsulate your rules and logic. One of the advantages of web services is that they work across boundaries and platforms. They also help you make your systems loosely coupled, only depending on the service contract and not a specific binary component. Web services use open standards such as HTTP, SOAP and XML to achieve interoperability and louse coupling.

Services do not deal in types or classes per se; rather, only with machine readable and verifiable descriptions of the legal "ins and outs" the service supports. The emphasis on machine verifiability and validation is important given the inherently distributed nature of how a service-oriented application is developed and deployed. Unlike a traditional class library, a service must be exceedingly careful about validating the input data that arrives in each message. Basing the architecture on machine-validatible schema and contract gives both developers and infrastructure the hints they need to protect the integrity of an individual service as well as the overall application as a whole. – Don Box

Blindly following the rule about not sharing class can lead to developers and architects forgetting what they know about object oriented design. This is something I have experienced on several projects. However, there is nothing in Don Box reasoning stopping you from building some really smart classes or libraries to help you consume and talk to these web services. Most development platforms have some sort of tool support to automatically generating proxies to create the SOAP messages needed to communicate with the service. However, since these classes are all generated based on WSDL and XSD definitions they don’t contain any "smarts", like validation rules, authorization, or computed properties.

There are different techniques to achieve sharing of some logic between server and client. An old trick is to move all your business entities into a separate assembly and use this on both server and client. After Visual Studio have generated a web service proxy you remove any generated types and include a using statement to the namespace containing your business entities. When the proxy de-serializes an Order-object from your web service it will create a "real" Order-object instead of an auto generated type. This object will have any validation rules or computed properties, which would be lost in the auto generated type. In Visual Studio 2003 and 2005 you had to do this by hand, which was bothersome, and something you had to redo every time you update your service reference. In Visual Studio 2008 this pattern is supported by the tool. When adding a new service reference you can choose to reuse any types in referenced assemblies, letting you use real objects instead of automatically generated proxy objects.

When working with Silverlight this is a little bit harder. The problem is that the client Silverlight .NET runtime is different from the server .NET runtime. You can’t directly reference a Silverlight class library in your web service application, or reference a traditional .NET class library in your Silverlight application. There are workarounds to help you share code between a .NET server application and a Silverlight client application. You can create two different class libraries, one for Silverlight and one for the server, and link the class files between them. You have one copy of the file, but it’s added to two different projects, letting you compile the same class into two different assemblies. Since Silverlight is a subset from .NET you may not be able to do all the same things in the client library as in the server library. You can separate out Silverlight and .NET specific code using compiler directives or partial classes.

#If Silverlight then 
    // Silverlight only code 
#Else 
    // .NET only code #End If 

This is the approach taken by Rockford Lhotka in CSLA Light, a trimmed down version for Silverlight of his CSLA.NET application framework. He recently started blogging about how CSLA Light helps you reuse business objects between tiers. This approach might be difficult if your server code have many external dependencies, for instance to ORM tools or other frameworks you don’t have a Silverlight version for.

Extending the automatically generated types

The web service proxies generated by Visual Studio have gotten better and better, and the classes generated by Visual Studio 2008 are quite useful. Sure, they won’t know about server specific rules, but the generated objects use properties, implements change notification and use observable collections for lists. This enables you to data bind against the proxy objects, which is really handy. However the solution isn’t perfect. One of the features added in Silverlight 2 Beta 2 is the support for binding validation. This enables you to detect if the data entered by the user in a data bound field breaks any validation rules. When the binding validation event fires you can highlight the field, for instance by changing background color. The way binding validation works in Silverlight 2 Beta 2 is by exceptions thrown in the setter of a property. If you bind against the automatically generated proxy objects you can’t change the setter to implement your validation rules.

Another example where you want to extend the proxy objects with additional functionality is for computed properties. Since I just got back from a dive trip I’m going to use that as an example. When logging a dive you enter date, time in water, bottom time and time out of water. If I were to implement a dive log application I would store the time the diver entered the water and the bottom time in the database. The time out of water would be a computed property, computed adding the bottom time (minutes) to the time the entered the water time. If I did this on my server, the data would get passed to the client, but the automatically generated proxy object would see this as any other "dumb" property. It wouldn’t understand the relationship between time-in water, bottom time and time-out of water. If I change the bottom time, the time out of water property wouldn’t change.

To solve these problems you have two options. You can choose to treat your web service objects as simple data transfer objects, and wrap them in your own custom client side objects. This can be done by creating a new DiveLogClient-object that takes the DiveLog proxy object in the constructor, and creates new properties for any field used by the UI. This approach gives you full flexibility but involves doing a lot of extra work. Another option is to create a partial class that extends the automatically generated proxy object. This class could add new properties, like TimeInClient, TimeOutClient and BottomTimeClient, which use the same private backing fields as the generated properties, but have additional logic needed to understand the relationship between time-in, bottom time and time-out. Your user interface would bind against the new properties instead of the generated properties, but since they use the same backing fields for their values you can still send the object back to the server to store any changes.

Is Microsoft doing anything to help?

Wanting to share some logic between the server and client is a common pattern. Surely Microsoft must be thinking about how they can help. By improving the service reference tool in Visual Studio Microsoft made it easier to share types across boundaries. But there is still allot that can be done. The Smart Client Software Factory contains functionality to map between service entities and business entities, which let you build richer business entities on the client, and get some framework support to map between the different types. But I’m sure they can do better…

Yesterday Microsoft announced 50 new session abstracts for PDC 2008 held in October. It’s really interesting to read the session abstract to get some ideas of unannounced products and project they are working. One of the sessions that caught my attention is "Microsoft Silverlight: Building Business Applications":

What if you could develop your solutions with the ease pioneered by Microsoft Office Access, deploy them like an Internet application, and take advantage of the power of Microsoft .NET? Learn about an exciting new technology that is all about making business applications for RIA (Rich Internet Applications) much easier to build. In this session, hear how we've made n-tier application development as simple as traditional 2-tier, provided application level solutions to developers, and how we're doing all of this with the same .NET platform and tools on both the client and server.

I guess it’s safe to assume that Microsoft have some really cool stuff in the works. Which approach they take to make n-tier development as simple as traditional 2-tier development I don’t know. But I wouldn’t be surprised to see some kind of smart sharing of linked code files, with partial classes or compiler directives to separate server and client code. It’s also interesting that SOA-expert Pat Helland has been working on a project in the area of RIAs, so hopefully he has been able to provide some valuable input on how to architect RIAs.

Which approach do I use?

Well, it depends… For larger Silverlight projects I tend to consider the automatically generated proxy objects as dumb data transfer objects that I wrap in business objects used by my Silverlight application. The advantage is that I get full control over the object, but the drawback is that I have to do more manual work… For smaller projects where I need minor changes I tend to use partial classes to extend the proxy objects with additional properties used by the client, but backed by the same fields as the properties that get serialized when sending the object back to the server. In the long run I’m a strong believer in tools or frameworks that help us reuse code between server and client in a clean way giving us something smarter than the proxies generated by Visual Studio. Frameworks like CSLA Light or the tools Microsoft will announce at PDC will probably help to deliver this. I expect the announcements at PDC to be to Silverlight what ASP.NET Dynamic Data is to web application. Dynamic Data lets you scaffold a complete data driven application, but without compromising customizability or generating tons of hard to maintain crappy code.

How do you share business logic between server and client?

blog comments powered by Disqus