Configuring and Deploying the LibroLogic Service
As you have seen, the implementation of the LibroLogic Service has been fairly straightforward. The real magic will happen within the configuration, which is one of the most powerful aspects of WCF. The decoupling of configuration and hosting from service implementation in WCF allows for tremendous flexibility in the design and implementation of your service-oriented applications, allowing for a separation of concerns among architects and developers. It cannot be stressed enough that WCF is all about productivity and is not merely a sexy new technology for writing SOA systems and service-oriented applications. If you are a .NET developer, it is the way to write enterprise .NET applications today, period. As a side note, consider Figure 4
, which plots the evolution of software engineering. At the simplest level, software engineering consists of the gradual, yet continuous decoupling of constituent artifacts, be it programs, objects, components, or services.
|Figure 4: The evolution of software engineering as a historic timeline. Each significant advancement in software technology is a result of reduced coupling.|
In WCF, you can configure services either programmatically or declaratively. For ease of configuration and to support changes in hosting environments, specifying binding configuration within an application configuration file is a great choice.
|The ability to think conceptually in terms of both "Big SOA" and "Little SOA" will give you a tremendous advantage in designing and implementing service-oriented applications that are sustainable and ready for change.|
As seen in Listing 6
, within the Services element, I have created an entry for the LibroLogic Service:
This entry allows you to associate one or more service endpoints with the service. As you might guess, you are going to expose a number of endpoints for each contract specifically designed for a specific transport so that at run time, the client can choose the best endpoint based on the status of the network.
Choosing Appropriate Bindings
According to the user features discussed at length, the LibroLogic Service must be available to the user in both online and offline mode. When online, the client should use the best transport protocol and support all operations provided by the LibroLogic Service. However, when the LibroLogic Service is offline, or the user loses network connectivity, the user should still be able to purchase a book using LibroLogic UI. Specifically, in the event that no network connection is available, the client should queue a purchase message so that when network connectivity is restored, the service can process the purchase message.
Table 1 provides some characteristics of the WsHttpBinding
, and NetMsmqBinding
bindings that WCF provides right out of the box, which will help you understand which binding is most appropriate for the given scenario addressed in this article. You can find a complete list of bindings and corresponding features
supported out of the box on MSDN.
Table 1. Characteristics of common WCF bindings.
Configuring the InventoryHTTP Endpoint
As you can see, WsHttpBinding
is the only interoperable binding of those listed. In a situation where network connectivity is available via the Internet, the LibroLogic UI should be able to connect to the store to communicate with the LibroLogic Service to query inventory or submit a purchase. To do this, messages must be able to traverse firewalls and routers along the way. For this use case, WsHttpBinding
is a perfect choice because it not only offers interoperability, but thanks to WCF's built-in support for WS-Reliable Messaging, it also offers reliability via a new standard pending ratification that provides reliable messaging despite the use of HTTP at the transport level. This is an important feature that is beyond the reach of vanilla Web Services today and will be the topic of a future article. For now, I have added an endpoint to handle requests over the HTTP protocol that uses the binding:
Configuring the InventoryTCP Endpoint
When working on site, there is no better choice than NetTcpBinding because it is fast, efficient, and inherently reliable since it uses the TCP at the transport level. Along with WS-Reliable Messaging, I will cover TCP in more detail in an upcoming article. For the time being, I'll expose an endpoint called InventoryTCP using the NetTcpBinding binding for use on site, where network connectivity is guaranteed (for the most part):
Configuring the RetailTCP and RetailHTTP Endpoints
In addition to supporting inventory-related operations such as querying for a particular book or flagging the book with a hold status, the goal of the service is to also support the ability to process retail-related transactions such as purchasing a book when the client is both on site and off site. In off-site scenarios, provided connectivity to the Internet is available, the client should use HTTP. For use on site, the client should use an endpoint called RetailTCP that is exposed using the NetTcpBinding binding. When off site, and provided a connection to the Internet is available, the client exposes an endpoint called RetailHTTP, which is powered by the WsHttpBinding to satisfy this requirement:
Configuring the RetailMSMQ Endpoint
The most interesting endpoint, at least for this article, is the RetailMSMQ endpoint. As you might imagine, the client will use this endpoint when the network is unavailable so that the user can still submit a purchase message to the LibroLogic Service.
There are additional features and benefits provided by using an MSMQ-powered endpoint including:
- Delivery Assurance: Messages sent to a NetMsmqBinding-powered endpoint are guaranteed to be delivered, even when the network or service/receiver is offline.
- Ordered Delivery: In some scenarios, maintaining the order of messages is important. For example, a business process is typically broken out into several discreet messages that are correlated at the receiver or more simply, the messages may need to be ordered in a way that describes a timeline or sequence of events.
- Durable Messaging: Once a queue receives a message, the message is persisted to disk and is able to survive machine restarts.
- Transacted Delivery: When working with transactional queues, a transaction can flow from the client all the way to the final receiver. MSMQ will automatically enlist itself as the root of a transaction and will not remove a message from its queue until it is either delivered to the ultimate receiver, and/or the transaction at the receiver successfully commits.
- Inherent Reliability: In addition to the reliability benefits provided by delivery assurance, durable messaging, and transacted delivery, you can configure MSMQ for a set retry interval. In addition, you can apply rules for how MSMQ should handle repeated failed delivery attempts.
There are certainly trade-offs to using the features above, and some thought does have to go into how to balance these offerings with throughput and performance requirements. However, when delivery assurance and transacted delivery is a must, leveraging MSMQ is a great choice.
While there is additional configuration required to support the MSMQ features just discussed (which I will review shortly), the basic endpoint configuration is very straightforward:
When a client invokes an operation on a service that the service exposes via a NetMsmqBinding-powered endpoint, an interesting thing happens. If the queue is remote (which in most cases, it almost always will be), and is available, depending on the additional binding configuration, WCF sends the message to the receiver queue. However, if the remote queue is unavailable, either because the Service Host was unable to receive requests or the network is down, WCF will automatically create a local queue on the client machine and write the message to queue. Then, based on retry criteria (which you can specify in configuration), the local queue will automatically try to resend the message.
In keeping with the theme of productivity, WCF makes the configuration of these details extremely simple by exposing several additional binding features.
Enabling Metadata Exchange
If you have been working with WCF for any period of time, you know that WCF takes the concept of explicit boundaries well, quite explicitly. Just as Data Contracts and Data Members along with Service Contracts and Operation Contracts are strictly opt-in, so too is the decision to expose metadata via a WSDL document. This is important because for clients to consume a service, they must be able to learn about what the service offers so that they can create the corresponding proxy types.
There are a couple of options for doing this, but a straightforward approach is to simply add a Service Behavior that instructs the Service Host that it is OK to provide a WSDL document when requested. We could certainly expose this metadata via multiple transport-specific endpoints, but one way to guarantee that all clients can learn about the service is to use an HTTP-based address as shown below:
You will notice that I've given the Service Behavior a name. Make sure that you remember to associate the name with the service via the behaviorConfiguration attribute on the service element. I get several questions on my blog and see similar questions on MSDN and other message boards where this simple oversight is the cause of a particular issue.
Installing and Configuring MSMQ
To proceed, you must have MSMQ installed on the machine in which you will host the service. You can get more information on installing MSMQ
Note that for this scenario, the sample code will use a private queue. This is the simplest way to demonstrate queued services in action and closely mimics the behavior of a WCF client that is interacting with a remote queue. It is important to note, however, that in a production scenario, it is very likely that the machine hosting the service would provide a public queue to which the private queue (installed on the client) would transmit messages in a transactional manner. Again, for the purposes of this example, both client and service will run on the same machine and will use a private queue.
Windows Activation Services (WAS), which ships today in Windows Vista and will ship as part of Windows Server 2008, will provide a first-class WCF hosting environment within IIS. While IIS is a perfectly suitable WCF host, it only supports HTTP-based binding. As such, it is not an option for this service, since the service needs to be able to support TCP, MSMQ, and HTTP transport protocols.
|When working on site, there is no better choice than NetTcpBinding because it is fast, efficient, and inherently reliable since it uses the TCP at the transport level.|
Since in WCF, any CLR host can host a service including Windows Services, Console Application, and Windows Forms, each of these options support all current bindings and are not limited to HTTP.
When you require a binding other than HTTP for a production-caliber scenario, Windows Services are the best option because they offer identity management and control of process startup and shutdown. For the purposes of this article, I will use a Console Application to demonstrate self hosting.
The code to host a WCF service is very simple:
static void Main(string args)
ServiceHost host = new
Console.WriteLine("LibroLogic Service is
catch (Exception ex)
Console.WriteLine("Error creating service host: "
When you instantiate ServiceHost, the Service Model will inspect the app.config
file for the required configuration if it is not provided programmatically.
If you right-click the LibroLogic.Host
project and then click "Debug" you should see a Console Application screen as shown in Figure 5
|Figure 5: The LibroLogic Service is hosted in a console application.||
|Figure 6: With Metadata Exchange enabled, you can browse the WSDL document.||
This is a perfect time to test the ability to discover the LibroLogic service as you are almost ready to generate the proxy necessary to consume the service from your test harness. Since you created an HTTP-based metadata exchange address, enter it in your browser as shown in Figure 6
. If your browser renders the WSDL document as shown, you are ready to consume the service!