Building Services Today
One of the readers of this blog asked if I have any guidance on how to design ASMX Services. I have had this question a lot recently, so I thought I'd better post some information:
We're currently working on an app that will demonstrate how to build SO systems using only today's technologies. We hope to publish this app in the next few months. I will blog about this as we get our plans in order. In the meantime, I hope the information below gives you a good starting point to jump off:
When designing Web Services, it's important to abide by the same rules you'd apply for designing any network addressable service or distributed app.
Key amongst these guidelines is “avoid the network wherever possible“. Otherwise stated - only traverse the network if you must and only pass across the network what you have to. I have stated this several times before in my Enterprise Services whitepaper and elsewhere in this blog. It is important when designing distributed systems to not fall into the trap of designing for architectural purity when building a service exposed to the network. One should generally take a very pragmatic approach and design methods that get the most done with the fewest network traversals. I urge you to concentrate on designing services that expose “chunky” methods that perform as much work as possible whilst passing only the information necessary to perform that task across the wire.
Here's an example of a “good“ service method:
[Serializable]
class Customer
{
string name;
int age;
DateTime dob;
}
[WebService]
class CustomerServices
{
...
[WebMethod]
void AddCustomer(Customer cust);
...
}
The following is an example of a “bad“ design since every time you need to add a customer you have to make several calls across the network to the service:
class CustomerServices
{
...
int CreateCustomer();
void SetCustomerName(int id, string name);
void SetCustomerAge(int id, int age);
void SetCustomerGlass(int id, string custClass);
...
}
The second main point I would like to suggest is to design your services to map to your business rather than mapping to the way your IT systems work internally.
When it comes to implementing your services internally, I suggest a design thought process such as:
- I implement my business functionality in one or more .NET internal implementation classes. These classes may or may not call other utility classes which talk to databases, queues, existing components, other systems, etc. These classes should make no assumptions (yet) about transactions, security etc. (since we've not yet decided how to host them)
- I then design an ASMX façade class that exposes the service to the outside world. This class should be made most applicable to callers of my service offering nice chunky “most bang for the buck“ operations.
- Now I consider my transactional needs.
- If I do not need distributed transactions, I implement my Web Service's methods by calling to my internal implementation class. For example, a given operation may simply connect to the database and call a stored procedure, passing in the supplied data. In this case, a transaction spanning several components is unnecessary, but if a simple transaction is required, ASMX Services can be marked as supporting transactions should you need to.
- If I need my business functionality to support distributed transactions spanning several components, I opt to write an EnterpriseServices façade class (attributed appropriately) which calls my internal implementation class. My Web Service façade class should call this ES façade class rather than directly calling my internal implementation.
- I also consider my queueing needs - if I need to pass messages via queues, I consider whether I can use Queued Components or whether formatting messages and sending them manually via MSMQ is the best approach.
- I also consider my Remoting needs. Am I talking x-AppDomain in the same process? Do I need to send this message in some strange format to a listener elsewhere? If so, then I need to design my remoting classes, but otherwise, I opt for EnterpriseServices wherever possbile.
Of course, this design process is not exhaustive, but it should indicate the kind of thinking one could take when designing Services.
Hope it helps.