This article is part of a series;
Unfortunately it is also the worst named post in the series J
It is a common requirement for customers to want to split web applications across physically separate tiers, usually using some kind of services technology. This post discusses some approaches to this using the Web Client Software Factory.
Although I focus on using WCF services, many of the concepts apply to ASMX and other technologies too – I have just chosen WCF as I believe it to be the best way to write services in the current .NET Framework environment.
* Note: Chances are I’m going to use the term Web Services a lot in this post. What I really mean when I say that is any kind of remote service – pretty much anything that can be written with WCF, for example.
Food for Thought
So first things first – let’s clear up some common myths.
1: SOA != Services
Just because your application uses Web Services (or any other kind of remote service), that doesn’t make it Service Oriented. It could still be just an app that uses Web Services. The current Wikipedia definition of SOA starts with a nice succinct statement about this;
“(SOA) is ... where functionality is grouped around business processes and packaged as interoperable services ... SOA separates functions into ... services ... which are made accessible over a network in order that they can be combined and reused in the production of business applications”.
In other words, if you’re writing a Web Service and Web Application as an inextricably linked pair that make up a single system, chances are you’re not doing SOA. SOA is an Enterprise Architecture, not an Application Architecture (although some applications will be built on the Enterprise Architecture by aggregating and reusing business services, and hence some apps are validly referred to as Service Oriented).
What this means to me is two things
1. Be pragmatic about what rules you follow when you are writing a completely isolated internal application.
2. Ask yourself this: “Why are we using a Web Service?” If your answer is “Because our company policy is that all new apps must be Service Oriented” (or something similar) I would recommend stepping back, and thinking deeply for a short while. How is adding a Web Service making your application Service Oriented? Is it really adding any value? If so, great – there are many valid reasons... but make sure you know what they are!
2: Services cost performance
Using a remote service is expensive (in terms of processing time, for example). If you previously had a method call that looked like this;
View.Orders = myBusinessLogic.GetOrders(user, startDate, endDate);
... and you move the implementation of GetOrders to be a remote Web Service, you will notice a significant performance degradation. Raw performance and scalability are often at odds like this! Suddenly we must serialize user information and dates, locate the remote service and open a channel, pass the data across a potentially unreliable network, spin up a service instance, deserialize the information, perform the business logic call that used to exist on the client, serialize the results, pass them back across the network, deserialize the results and turn them into a .NET list, and finally close the channel to the remote service. Phew. Now all that might be pretty fast in .NET, but it will be slower than an in-process method call.
Having said that, if the logic you must execute is expensive itself, you may find that removing load from the client Web Server and scaling it out to another physical tier improves the scalability of your system. I’m not saying don’t use services here – I just want you to be realistic about it!
3: RPC != Messaging
Because services add overheads, it is important to adopt a message exchange approach rather than a remote procedure call approach. What does this mean? Basically it comes down to two things;
1. Granularity. RPC consists of chatty, frequent calls between client and service, very quickly making it difficult to scale your system. When you think RPC, think of many systems written with Remoting or Java’s RMI. Message exchanges are courser grained and minimise the amount of calls and proportion of overheads involved.
2. Programming Model. I tend to find that RPC encourages the sharing of concepts internal to a service with the outside world. Use a message oriented approach makes you think about defining the contracts, abstracting where necessary, and encapsulating behaviour appropriately. Watch for a future post on the Service Interface pattern when I get a chance!
So now that we’ve thought a little about what we want to avoid, let’s see a couple of approaches and discuss their characteristics.
First up is our baseline architecture; this is what future examples will evolve from, and represents a basic WCSF application (ignoring splits across modules) without any kind of service layer.
Note that I’ve decided to expose my business logic here using a WCSF application service (not a web service). This communicates with my “model” (basically the business logic), which in turns talks to various data access classes (e.g. DbAccess). I hope that’s pretty straightforward.
2: Split Tiers
I nearly named this “RPC approach” because I feel that it encourages an RPC style of programming. Components above the dotted line are in my WCSF Web Application, and those below it are in the WCF Web Service.
What we have done here is just move the logic into a Web Service, and then change the WCSF application service that previously exposed business logic to purely act as a facade to the remote Web Service – in other words, it is a Service Agent or Service Proxy. This is a key concept – a Web Service is a resource, so if you are communicating with a Web Service directly in a class, you’re writing a resource (or data) access component.
The problem with this approach, in my opinion, is that this encourages developers to just call methods as though they were local to the web application, potentially leading to an RPC style system with very chatty communications and a serious scalability problem. Often people don’t realise that they are effectively writing an application that has no business logic layer (the Web Application)!! This is obviously contrary to well understood wisdom nowadays, and looking at the diagram above, I hope you see how unnatural it looks.
This lack of separation can also lead to changes in the service contracts affecting the UI. This is by no means ideal.
3: Remote Services
My preferred approach is shown below;
Here you can see that our missing logic layer has made a triumphant return! This might seem subtle but I think it completely changes class responsibilities and how your developers perceive the system. The logic in the Web Application is responsible for deciding when to go to a web service, or when to use a local cache, how to co-ordinate calls between different resources (you might have multiple web services!), when to enforce security or other policy, and so on. This then leaves your Resource Access layer able to dedicate itself to providing a real shield from the inner workings of the service calls.
As I’m sure regular readers have noticed, I’m a big fan of talking in concrete examples, so let’s see some (simplified) code that demonstrates this approach. Firstly, the Presenter and implied View;
public class MyPresenter<IMyView>
private ILogicService _logicService;
public MyPresenter([ServiceDependency] ILogicService logicService)
_logicService = logicService;
public void OnRetrieveOrders()
List<OrderEntity> results =
View.Orders = results;
The key here is that the presenter is using a WCSF service (badly named as ILogicService) to fetch orders for display to the user. These orders are represented by an “OrderEntity” entity. Next, let’s see an example of an ILogicService implementation;
public class LogicService : ILogicService
private IAuthenticationService _authenticationService;
private IEntityTranslatorService _entityTranslatorService;
_authenticationService = authenticationService;
_entityTranslatorService = entityTranslatorService;
public List<OrderEntity> FetchOpenOrdersForCurrentUser(
OrderServiceProxy proxy = null;
proxy = new OrderServiceProxy();
string orderStatusCode =
List<Order> orders = proxy.GetOrders(
List<OrderEntity> results =
if (proxy != null)
There are a few really important points to make here;
1. I have chosen to abstract environmental issues, such as authentication, away into a framework service. See my previous post on Environment Abstraction for more information on this.
2. All the management of the interaction with the service proxy is kept out of the Presenter, and instead is handled by our WCSF application service.
3. I am performing Entity Translation between the “Order” and “OrderEntity” objects. The former is actually part of the definition of the Order Service’s Service Contract, in that it defines how the remote service is communicated with. The latter is a Business Entity defined by my WCSF module. Therefore it is important that I expose the Business Entity not the proxy communication entity further up my architecture.
4. The service performs some limited Orchestration – it calls a number of methods on the service to achieve what is seen by the Presenter as a single business operation. Obviously I would prefer a very course grained service design, but I’ve done this to illustrate that this is the right place to perform any required orchestration (potentially across multiple services) and workflow.
5. The disposal of the proxy is done correctly. A “using” block is not the best way to deal with WCF proxies – see Avoiding Problems with the Using Statement.
6. This is also the right place for rich error handling, publishing, and compensation – please don’t follow my poor example in this respect J
7. I haven’t used the rich implementation of the Service Interface pattern I would usually, because constructing the messages would increase the volume of sample code and detract from the point. I’ll probably post about Service Interfaces soon, so watch this space!
The final important point is that this separation of business logic, resource access, entity translation, etc is likely to be repeated by the Order Service.
When using WCF proxies there are a number of things worth knowing about. The first is the best way to use a “using” block, mentioned above.
Secondly, remember that a WCSF service is a singleton – so if you cache the WCF proxy you will be using the same one for every call, no matter which end user is browsing your site. No probs... oh, hang on! But what if you’re using a session-full binding? That would mean all your WCF calls would be using the same session, no matter which end user the call was for! This could certainly be a problem – so be very careful about this.
Thirdly, if you are caching your WCF proxy remember that a faulted proxy cannot be used again. So if your backend service fails and then comes back up, and you’re caching the proxy forever and for every user, your web application will be unusable until you cause it to flush the cache (e.g. by restarting the App Pool). The correct way to handle a faulted proxy is by adding the following code when creating it;
proxy = new OrderServiceProxy();
In the event handler you can then react in some way – perhaps by Aborting the proxy and replacing it with a fresh one. This is obviously pretty academic for my example code above, but if you are caching proxies, consider this carefully. Also, if you don’t have a business logic layer, you might find it more difficult to deal with this kind of situation!
Finally, I’ve used the class generated by “Add Service Reference” in Visual Studio. It is actually pretty slow to new up one of these for every business operation when compared to using a cached ChannelFactory. In .NET 3.5 this is less true, but I’d recommend this post comparing the two approaches.
There are many issues I’ve not covered here – security architecture, for example (Trusted Subsystem versus Delegation), and many, many, many, more. But I hope this has gotten you started on how to structure your code, freeing you up to investigate some of the more subtle complexities. Good luck!
And finally... a Summary of Summaries
This is the last post in my series on Web Client Software Factory Application Architecture. That doesn’t mean I’ll not post about WCSF again of course, just that we have now covered plenty, from the basic patterns involved to some more “fluffy” concepts of designing modules or service layers. I hate television series that have no end (wow, it is seriously difficult not to name and shame here, that’s how much I hate it!), so I’ll take my own advice and finish on a high J
Remember how much I haven’t covered – there is plenty of information out there, from the WCSF community site, landing page, other bloggers, obviously in the factory documentation, and so on. And if you’re blogging about it, do let me know!