Chapter 3 — Getting Connected

 

patterns & practices Developer Center

Smart Client Architecture and Design Guide

David Hill, Brenton Webster, Edward A. Jezierski, Srinath Vasireddy and Mohammad Al-Sabt, Microsoft Corporation; Blaine Wastell, Ascentium Corporation; Jonathan Rasmusson and Paul Gale, ThoughtWorks; and Paul Slater, Wadeware LLC

June 2004

Related Links

Microsoft® patterns & practices Library https://msdn.microsoft.com/en-us/practices/default.aspx

Application Architecture for .NET: Designing Applications and Serviceshttps://msdn.microsoft.com/en-us/library/ms954595.aspx

Summary: This chapter describes a number of ways in which your application can connect to and use network resources, along with components or processes on the client computer, and discusses the strengths and weaknesses of each.

Contents

Loosely Coupled and Tightly Coupled Systems
Communication Options
Choosing a Communication Option
Designing Connected Smart Client Applications
Summary

By definition, smart clients need to connect to and communicate with other resources and form part of a distributed application. These resources can be client-side processes or components, or they may be network resources, such as a Web service.

This chapter examines the nature of communication between smart clients and other resources. It looks at the different technologies available for connecting and using resources in other processes, components, or remote services, and it discusses how to choose between them. Finally, it examines how best to design your smart clients to connect to resources.

Loosely Coupled and Tightly Coupled Systems

A client application can connect to and use components and services in other processes, both locally and on the network, in many different ways. It is useful to categorize the different approaches by how much coupling exists between the service and the client.

Coupling is the degree to which components (in a distributed system) depend on one another. The nature of coupling between clients and the services they communicate with can affect many aspects of the smart client design, including interoperability, offline capabilities, network communication performance, deployment, and maintenance considerations.

Tightly coupled systems often provide direct object-to-object communication, with the object on the client having detailed knowledge of the remote object. Such tight coupling can prevent independent updates to the client or the server. Because tightly coupled systems involve direct object-to-object communication, objects usually interact more frequently than in loosely coupled systems, which can cause performance and latency problems if the two objects are on separate computers and are separated by a network connection.

Loosely coupled systems are often message-based systems, with the client and the remote service unaware of how the other is implemented. Any communication between the client and service is dictated by the schema of the message. As long as the messages conform to the agreed-upon schema, the implementation of the client or service may be changed as required without fear of breaking the other.

Loosely coupled communication mechanisms offer a number of advantages over tightly coupled mechanisms, and they help to reduce the dependency between the client and the remote service. However, tight coupling often provides performance benefits and allows for a tighter integration between the client and the service, which may be required due to security or transactional requirements.

All distributed clients that communicate with remote services or components have some degree of coupling. You need to be aware of the different characteristics between the various loosely coupled and tightly coupled approaches so you can choose the right degree of coupling for your application.

Communication Options

When you design your smart client application, you can choose from a number of methods to connect it to other resources, including:

  • Microsoft® .NET Enterprise Services.
  • Microsoft .NET remoting.
  • Microsoft Windows® Message Queuing (also known as MSMQ).
  • Web services.

.NET Enterprise Services

You can use .NET Enterprise Services to provide access to the COM+ service infrastructure of managed code components and applications. .NET components rely on COM+ to provide them with a number of component services, such as:

  • Transaction support.
  • Role-based security.
  • Loosely coupled events.
  • Object pooling.
  • Queued components.
  • Just-in-time activation.

A .NET component that uses COM+ services is known as a serviced component. Because your serviced components are hosted by a COM+ application, they must be accessible to that application. This introduces a number of registration and configuration requirements for the serviced component:

  • The assembly must be derived from the ServicedComponent class in the System.EnterpriseServices namespace.
  • The assembly must be strong-named.
  • The assembly must be registered in the Microsoft Windows registry.
  • Type library definitions for the assembly must be registered and installed into a specific COM+ application.

Assemblies that contain serviced components that are configured as out-of-process applications should be placed in the global assembly cache. Assemblies that contain serviced components configured as in-process libraries need not be placed in the global assembly cache, unless they are located in a different directory than the application. If you deploy multiple copies of the same version of a serviced component in this way, the COM+ catalog contains the global configuration for all instances of that component; it is not possible to configure them on a per-copy basis.

The following code example shows a component that requires a transaction and provides a method that writes data to a database within this transaction.

using System.EnterpriseServices;

[Transaction( TransactionOption.Required )]
public class CustomerAccount : ServicedComponent
{
[AutoComplete]
public bool UpdateCustomerName( int customerID, string customerName )
{
            // Updates the database, no need to call SetComplete.
            // Calls SetComplete automatically if no exception is thrown.
}
}

Serviced components can often register dynamically the first time they run. This type of registration is known as lazy registration. The first time a managed code application attempts to create an instance of a serviced component, the common language runtime (CLR) registers the assembly and the type library, and it configures the COM+ catalog. Registration occurs only once for a particular version of an assembly. Lazy registration allows you to deploy serviced components using Xcopy deployment and to work with serviced components during the development cycle without having to explicitly register them.

Lazy registration is the easiest method for registering your serviced components, but it works only if the process running them has administrative privileges. Also, any assembly that is marked as a COM+ server application requires explicit registration; dynamic registration does not work for unmanaged clients calling managed serviced components. In cases where the process that uses the serviced component does not have the required privileges for dynamic registration, you need to explicitly register the assembly containing the serviced component using the Regsvcs.exe tool provided with the .NET Framework.

Both lazy registration and Regsvcs.exe require administrative permissions on the client computers, so if your application includes serviced components, it cannot be deployed using no-touch deployment. For more details, see Chapter 7: Deploying and Updating Smart Clients

Serviced components can be hosted and accessed in a number of different ways. They can be hosted within an ASP.NET application and accessed through HTTP, or they can be accessed through SOAP or DCOM (the default setting). However, if the COM+ services need to flow with the call (for example, if you need the user's identity or a distributed transaction to flow from your application to the serviced component), DCOM is the only viable solution.

**Note   **If you use DCOM to communicate with COM+ applications, you need to deploy interop assemblies to the client computers, just as you would for traditional COM components.

Enterprise Services have many powerful component features that you can use in your smart client applications. However, you should usually use these features only within a single process, on a single client computer, or within a service boundary on the server. Enterprise Services are generally not the best choice for communication between a smart client application and services located on remote systems due to their tightly coupled nature. Use Enterprise Services if your smart client application needs to use COM+ services locally (for example, support for transactions, object pooling, or role-based security).

For more information about Enterprise Services, see "Writing Serviced Components" in .NET Framework Developer's Guide at https://msdn.microsoft.com/en-us/library/3x7357ez(VS.80).aspx.

.NET Remoting

.NET remoting provides a flexible and extensible remote procedure call (RPC) mechanism by which .NET components can communicate. .NET remoting allows you to use a variety of communication protocols (such as HTTP or TCP), data encoding options (including XML, SOAP, and binary encoding) and various object activation models. It can provide a fast and efficient means of communication between objects.

.NET remoting allows you to call remote objects as though they are local by using a proxy object that appears to be the remote object. The .NET remoting infrastructure handles the interaction between the client code and the remote object through property and method calls, encoding the data to be passed between them and managing the creation and deletion of the remote target object.

The .NET remoting infrastructure requires that the client has detailed knowledge of the public methods and properties of the remote object to provide a client-side proxy. One way of ensuring that the client has this knowledge is to distribute a full implementation of the remote object to the client. However, it is much more efficient to factor in the public methods and properties to interface definitions and compile these interfaces into their own assembly. The interface assemblies can then be used by the client to provide a suitable proxy, and they can be used by the remote object to implement the necessary functionality. This technique also allows you to update the implementation of the remote objects without having to redistribute the full objects to the client.

You can manage the lifetime of remote objects in a number of ways. Objects can be created on demand to fulfill a single request, or you can control their lifetime more finely by using a lease mechanism, where the client maintains a lease on the remote object and the remote object is kept alive as long as the client wants to use it. .NET remoting can also guarantee that only one object instance exists for all clients. You can choose the lifetime for your application according to your requirements for state management and scalability.

The extensible infrastructure of .NET remoting allows you to create custom channels and sinks. Custom channels allow you to define the way in which data is transmitted over the network. For example, you can define a custom channel to implement a custom wire protocol. Custom sinks allow you to intercept and perform actions on the data as it is sent between objects. For example, you can define a custom sink to encrypt or compress the data before and after transmission.

.NET remoting has a powerful and extensible mechanism for communicating between objects. However, due to its tightly coupled nature, it may not be suitable for all situations. .NET remoting requires .NET-implemented objects on both the client and server; therefore, it is not suitable for situations in which interoperability between different environments is a requirement. .NET remoting is also not suitable in situations where tightly coupled RPC-style interaction between client and server is inappropriate. By default, .NET remoting does not provide any built-in mechanism for encryption or for passing the user's identity or a transaction between objects. For these situations, Enterprise Services should be used.

.NET remoting is a good choice, however, for communicating between objects in different processes on the client computer or within a service boundary, or for objects in different application domains.

For more details about using .NET remoting, see "An Introduction to Microsoft .NET Remoting Framework" at https://msdn.microsoft.com/en-us/library/ms973864.aspx.

For information about choosing between Web Services and Remoting, see "ASP.NET Web Services or Remoting: How to Choose" at https://msdn.microsoft.com/en-us/library/ms978420.aspx.

Message Queuing

With Microsoft Windows Message Queuing, it is easy for you to communicate with applications quickly and reliably by sending and receiving messages. Messaging provides you with guaranteed message delivery and a reliable way to carry out many business processes. Message Queuing provides a loosely coupled communication mechanism you can use within your smart client application. Message Queuing has the following features:

  • Guaranteed message delivery. Message Queuing guarantees that messages are delivered despite the failure or absence of the remote system by storing messages in a queue until they can be delivered. Therefore, messages are considerably less affected by failures than are direct calls between components.

  • Message prioritization. More urgent or important messages can be received before less important messages, which can help to guarantee adequate response time for critical applications.

    **Note   **You can set message priority only for nontransactional messages.

  • Offline capabilities. If messages cannot be delivered because the client is offline, they are stored in the outgoing queue and are delivered automatically when the client goes back online. Users can continue to perform operations when access to the destination queue is unavailable. In the meantime, additional operations can proceed as if the message had already been processed, because the message delivery is guaranteed when the network connection is restored.

  • Transactional messaging. You send messages as part of a transaction. In this way, you can send several related messages or design your application to participate in a distributed transaction, and ensure that all messages are delivered in order and are delivered only once. If any errors occur within the transaction, the entire transaction is cancelled and no messages are sent.

  • Security. The Message Queuing technology on which the MessageQueue component is based uses Windows security to secure access control, provide auditing, and encrypt and authenticate the messages your component sends and receives. Message Queuing messages can be encrypted on the wire to make them impermeable to packet sniffers. You can also prevent queues from receiving unencrypted messages.

Applications that use Message Queuing can send and read messages from queues by using the classes in the System.Messaging namespace. The Message class encapsulates a message to be sent to a queue, while the MessageQueue class provides access to a specific queue and its properties.

You need to install and configure Message Queuing on any computer that will use it. Message Queuing is available for Windows desktop operating systems and for Microsoft Windows CE .NET, allowing you to use it on mobile devices such as Pocket PC devices.

Message Queuing is a good choice for interacting with services that provide message-based access. You can use Message Queuing to communicate with other systems that have Message Queuing installed. Interoperability with other systems is limited, though you can use connectivity toolkits to communicate with other messaging systems such as MQSeries from IBM.

For more information about using Message Queuing, see "Message Queuing (MSMQ)" in the Microsoft Platform SDK documentation at https://msdn.microsoft.com/en-us/library/ms711472(VS.85).aspx.

For information about MSMQ-MQSeries bridge programming, see "Programming Considerations Using MSMQ-MQSeries Bridge Extensions" at https://msdn.microsoft.com/en-us/library/ee266451(BTS.10).aspx.

Web Services

A Web service is an application component that:

  • Exposes useful functionality to other Web services and applications through standard Web service protocols.
  • Provides a detailed description of its interfaces, allowing you to build client applications that communicate with it. The description is provided in an XML document called a Web Services Description Language (WSDL) document.
  • Describes its messages by using an XML schema.

The SOAP-based XML messages of Web services can have explicit (structured and typed) parts or loosely defined parts (using arbitrary XML). This means that Web services can be either loosely coupled or tightly coupled and can be used to implement message-based or RPC-style systems, depending on the precise requirements of your environment.

You can use Web services to build modular applications within and across organizations in heterogeneous environments. These applications can be interoperable with a broad variety of implementations, platforms, and devices. Any system that can send XML over HTTP can use Web services. Because Web services are based on standards, systems written in different languages and on different platforms can use each other's services. This is often referred to as a service-oriented architecture.

The main standards used with Web services are HTTP, SOAP, UDDI, and WSDL. Web services are agnostic to transport protocols. However, HTTP is the most common mechanism for transporting SOAP messages. Therefore, Web services are well suited for applications that traverse networks and corporate firewalls, such as smart clients that need to communicate with services over the Internet.

A number of Web services standards are emerging to extend the functionality of Web services. Microsoft Web Services Enhancements (WSE) 2.0 supports emerging Web services standards such as WS-Security, WS-SecureConversation, WS-Trust, WS-Policy, WS-Addressing, WS-Referrals, and WS-Attachments and Direct Internet Message Encapsulation (DIME). WSE provides a programming model to implement various specifications that it supports. For more information, see "Web Service Enhancements (WSE)" at https://msdn.microsoft.com/en-us/netframework/aa663324.aspx.

For more information about SOAP, see "Understanding SOAP" at https://msdn.microsoft.com/en-us/library/ms995800.aspx.

For more information about WS-Security, see "Web Services Security Specifications Index Page" at https://msdn.microsoft.com/en-us/library/ms951273.aspx.

Web service communications can be coarse-grained, self–contained, and stateless. However, Web services are often very verbose compared to other forms of communication.

Web services are the best approach for building most smart client applications. The high degree of interoperability allows Web services to communicate with a wide range of applications. The use of widely adopted standards means that they can usually pass through network infrastructure and firewalls with minimal additional configuration (compared to other technologies that require proprietary ports to be opened). Strong support for Web services in the Microsoft Visual Studio® development system means that you can work with them in a single development environment.

Web services may not be appropriate in extremely high performance applications because they are verbose and contain relatively heavy message payloads compared to other messaging technologies such as .NET remoting and Message Queuing.

For more information about using and building Web services, see "XML Web Services Created Using ASP.NET and XML Web Service Clients" in .NET Framework Developer's Guide at https://msdn.microsoft.com/en-us/library/7bkzywba(VS.71).aspx.

Choosing a Communication Option

Different communication options are appropriate in different situations. Table 3.1 summarizes the different options for getting connected.

Table 3.1   Smart Client Options

Option Advantages Disadvantages
Enterprise Services Provides access to COM+ services

Allows identity to flow with call

Requires serviced components to be installed at the client

Suitable only for same process or computer

.NET remoting Fast

Pluggable

Supports custom protocols

Requires .NET Framework to run

Proprietary

Cannot traverse firewalls without RPC ports open

No security infrastructure

Message Queuing Useful for communicating with messaging systems

Secure

Guaranteed message delivery

Requires Message Queuing to be configured on the client

Does not integrate easily with other systems

Web services Supports integration

Extensible

Strong industry support

Clearly defined standards

Vendor/language agnostic

Secure

Verbose

Performance slower than .NET remoting

As Table 3.1 illustrates, there are some situations in which Enterprise Services, NET remoting, and Message Queuing may be appropriate technologies for communication between smart clients and the connected resources. However, in most cases, Web services are the best mechanism for connecting smart client applications to services.

An architecture built around Web service communication can work well in both a connected and offline environment, with support for coarse-grained, stateless messages that are self-describing and self-contained. The reliance on Internet protocols allows for wide distribution of the client to anyone on the Internet.

Designing Connected Smart Client Applications

As you design your smart clients, there are a number of recommendations you should consider, including:

  • Using coarse-grained, encapsulated messages.
  • Avoid distributed ACID transactions.
  • Avoid sending datasets across the network.
  • Break up large datasets.
  • Version your Web services and assemblies.

Use Coarse-Grained, Encapsulated Messages

Distributed network calls are expensive operations. You should not design your external interfaces in the same fine-grained way you would design local interfaces, or performance will suffer. To avoid message dependencies between messages, it is a good idea to build interfaces methods as self-contained functions. Doing so saves you from writing complex tracking reconciliation code to handle the failure of a message that depends on the successful completion of another.

Avoid Distributed ACID Transactions

Distributed ACID (atomic, consistent, isolated, durable) transactions are resource-intensive, with a lot of network traffic and a lot of interdependent system locks on pending local transactions. If your smart client or service is waiting for a reply and cannot continue until the reply is received, a distributed ACID transaction can block business processes.

The problems of distributed ACID transactions are exacerbated if your smart clients are likely to switch to offline mode without warning. In this case, a client may place a lock on data and go offline before the lock can be released at the server.

If you cannot avoid message dependency by breaking up your interfaces into single discrete messages, you have a number of options to deal with transactions and still avoid distributed ACID transactions:

  • Submit tightly coupled messages to the server and have a transaction coordinator such as Microsoft BizTalk® Server handle message dependencies.
  • Write transaction-compensating code yourself on the client or server. Use a communications protocol that the server can use to decide when to start a transaction and how to notify the client regarding the successful completion or failure of the transaction to be processed in its entirety.

Avoid Sending Datasets Across the Network

Datasets can be too big and verbose to use as a communication payload mechanism for sending data across many tiers. Instead, you should use data transfer objects (DTOs) to decrease the message payload to your external interfaces. For data changes, you should consider sending the only the changed data instead of the entire set of data.

For more information about DTOs see Chapter 2: Handling Data

Break Up Large Datasets

Large datasets can cause performance problems at the client if you try to display them all at the same time. Therefore, you should break them up into smaller datasets. Breaking up data in this way is known as paging. For example, instead of displaying the entire contents of a phone directory, you may choose to display one page at a time (for example, 20 records per screen, displayed alphabetically). If you design the client to use paging, you should ensure that the user interface is designed to make navigating between pages easy for the user.

This concept of breaking up large datasets also applies to communication with the server over the network. If you can break the data into manageable chunks, you can then load the required data on an as-needed basis, a technique known as lazy loading. In the phone directory example, only the data needed for the current operation would be loaded, reducing the impact on the application and on the network, and potentially making both more responsive.

To improve the user experience, you can use additional threads to perform background processing and communication with services in anticipation of upcoming user requests.

Although support for lazy loading may be an important aspect of your smart client application design, you should bear in mind the offline requirements of your application. Lazy loading of data that travels over the network may prevent your application from functioning offline as you hope.

Version Your Web Services and Assemblies

When you upgrade and release new versions of your smart client software to clients, you should create new versions of the assemblies. If you use versioned assemblies, and if you design your server services to support backward-compatible interfaces, you can support multiple versions of the client software. When releasing new versions of your Web services, you should differentiate them with a canonical naming convention. Alter the namespaces of each release so that they contain date information to make it clear what version of a Web service clients are communicating with.

For more details about handling multiple versions of assemblies, see Chapter 7: Deploying and Updating Smart Clients

Summary

Smart clients need to access resources, both local and remote, to function. How you handle this communication can be critical to your success in designing smart clients that are reliable and responsive to the user. Requirements such as performance, security, and flexibility affect what the appropriate connectivity choice is for your environment. Using the guidance in this chapter, you should determine which forms of connectivity are right for your smart clients, and then design your smart clients and the resources with which they communicate accordingly.

patterns & practices Developer Center

© Microsoft Corporation. All rights reserved.