Note that the information on this page is the BETA 1 of a guide that is now released. See
http://www.codeplex.com/AppArchGuide for the latest PDF and HTML content.
Chapter 20 – Rich Client Applications
- J.D. Meier, Alex Homer, David Hill,
Prashant Bansode, Lonnie Wall, Rob Boucher Jr, Akshay Bogawat
- Define a Rich Client Application.
- Identify key scenarios where Rich Client applications would be used.
- Identify components found in a rich client application.
- Learn about design considerations.
- Identify deployment scenarios for Rich Client applications.
Rich client user interfaces can provide high performance, interactive, and rich user experiences for applications that must operate in stand-alone, connected, occasionally connected, and disconnected scenarios. Windows Forms, WPF, and Office Business Application
(OBA) development environments and tools are available that allow developers to quickly and easily build Rich Client applications. While these technologies can be used to create standalone applications, they can also be used to create applications that run
on the client machine, but communicate with services exposed by other layers (both logical and physical) that expose operations the client requires. These operations may include data access, information retrieval, searching, sending information to other systems,
backup, and related activities.
Rich Client Applications can range from fairly thin interfaces that overlay business layers and service layers, to complex applications that perform most of the processes themselves and just communicate with other layers to consume or send back information.
An example is the difference between an application such as an FTP client that depends on a remote server to provide all of the data for display, and an application like Microsoft Excel that performs complex local tasks, stores state and data locally, and
only communicates with remote servers to fetch and update linked data.
Therefore, the design and implementation of a Rich Client varies a great deal. However, in presentation layer and User Interface UI terms, there are some common approaches to good architectural design. Most of these are based on well-known design patterns.
Many of these patterns encourage the use of separate components within the application that reduce dependencies, make maintenance and testing easier, and promote reusability.
Some Rich Client applications are effectively stand-alone, and rely only on data retrieved and sent back to other layers of the application and to other applications. These types of Rich Client may contain their own business layers and data access layers. They
may also expose business and data services for other applications to use. The guidelines for the business and data layers in such applications are the same as those discussed generally for all applications.
The Rich Client application contains:
- Presentation layer components, which include UI Components and UI Processing components.
- Business layer components, which include Business Workflow, Business Processing, Business Entities, and optionally a Façade.
- Data Layer components, which include Data Access Components, Data Helpers/Utilities, and Service Agents.
The following is a description of the different component types listed above.
- User interface (UI) components. User interface components provide a way for users to interact with the application. They render and format data for users and acquire and validate data coming in from them.
- User process components. To help synchronize and orchestrate these user interactions, it can be useful to drive the process using separate user process components. This way the process flow and state management logic is not hard-coded in the user
interface elements themselves, and the same basic user interaction patterns can be reused by multiple user interfaces.
- Business components. Business components implement the business logic of the application. Regardless of whether a business process consists of a single step or an orchestrated workflow, your application will probably require components that implement
business rules and perform business tasks.
- Business workflows. After the required data is collected by a user process, the data can be used to perform a business process. Many business processes involve multiple steps that must be performed in the correct order and orchestrated. Business
workflows define and coordinate long-running, multi-step business processes, and they can be implemented using business process management tools.
- Business entity components: Business entities are for passing data between components. The data is used to represent real-world business entities, such as products or orders. The business entities that are used internally in the application are usually
data structures, such as DataSets, DataReaders, or Extensible Markup Language (XML) streams, but they can also be implemented using custom object-oriented classes that represent the real-world entities your application has to work with, such as a product or
- Application Facade. (Optional). Use to combine multiple business operations into single messaged based operation. You might access the application façade from the presentation layer using different communication technologies.
- Data access logic components. Data access components abstract the logic necessary to access your underlying data stores. Doing so centralizes data access functionality and makes it easier to configure and maintain.
- Data Helpers/Utilities. Implement data helpers for centralizing generic data access functionality such as managing database connections and caching data. You can design data source specific helper components to abstract the complexity of accessing
the database. Avoid adding any business logic to the helper components.
- Service agents. When a business component needs to use functionality provided in an external service, you may need to provide some code to manage the semantics of communicating with that particular service. Service agents isolate the idiosyncrasies
of calling diverse services from your application, and can provide additional services, such as basic mapping between the format of the data exposed by the service and the format your application requires.
When designing Rich Client applications, consider the following guidelines:
- Choose an appropriate technology. Technologies include Windows Forms, Windows Presentation Foundation (WPF), XAML Browser Applications (XBAP), and Office Business applications (OBA).
- Separate presentation logic from interface implementation. Design patterns such as MVC and Supervising Controller separate the UI rendering from UI processing, which eases maintenance, promotes reusability, and improves testability.
- Identify the presentation tasks and presentation flows. This will help you to design each screen, and each step in multi-screen or Wizard processes.
- Design to provide a suitable and usable interface. Take into account features such as layout, navigation, choice of controls, and localization to maximize accessibility and usability.
- Extract business rules and other tasks not related to the interface. A separate business layer should handle tasks not directly related to presentation, or related to collecting and handling user input.
- Reuse common presentation logic. Libraries that contain templates, generalized client-side validation functions, and helper classes may be reusable in several applications.
- Identify the business and data layers. This will indicate how your interface and code will communicate with other layers of the application.
- Loosely couple your client from remote services it uses. Use a message-based interface to communicate with services on separate physical tiers.
- Avoid tight coupling to objects in other layers. Use the abstraction provided by common interface definitions, abstract base classes, or messaging when communicating to other layers of the application. For example, implementing the Dependency Injection
and Inversion of Control patterns can provide a shared abstraction between layers.
- Reduce round trips when accessing remote layers. Use coarse-grained methods and execute them asynchronously if possible to avoid blocking or freezing the user interface.
Rich Client Frame
||Choosing the wrong communication protocols and technology
||Using synchronous communication methods when asynchronous methods could provide better interface performance
||Failing to properly detect and manage disconnected or occasionally connected scenarios
||Using fine-grained "chatty" interfaces across physical tiers
||Choosing an inappropriate composition technology
||Not managing auto-update and versioning of composable components
||Failing to take advantage of appropriate templating and data-binding technologies
||Failing to take into account personalization requirements
||Failing to correctly manage configuration information
||Not securing sensitive configuration information
||Failing to identify the appropriate configuration options and information
||Failing to take into account Group Policy overrides
||Failing to design support for the appropriate data format, such as custom objects, Table Module, Domain Model, Data Transfer Objects, or DataSets
||Failing to correctly manage offline data access, concurrency, and subsequent synchronization
||Not minimizing data returned from remote services and layers
||Failing to support large sets of data when required
||Not planning a strategy for handling and managing exceptions
||Raising exceptions when not appropriate
||Failing to sanitize exceptions and remove sensitive information
||Not implementing appropriate logging and auditing functionality
||Failing to support administrative and remote management and error-reporting requirements
||Failing to correctly store and manage UI state information
||Failing to cache state where this is appropriate
||Choosing an inappropriate cache store
||Failing to protect and secure sensitive state information
||Failing to support transactions where required
||Failing to design and implement an appropriate workflow or viewflow mechanism
||Not implementing error and exception management for workflows and viewflows
Rich Clients can communicate with other layers of the application and with other services using a variety of protocols and methods. These may include HTTP requests, SMTP email messaging, SOAP Web service messages, SNTP time synchronization packets, DCOM for
remote components, and many other TCP/IP-based standard or custom communication protocols. Alternatively, if the client application is located on the same physical tier as the business layer, then you should use object-based interfaces to interact with the
When designing a communication strategy, consider the following guidelines:
- Identify the communication protocols that the application requires. Firewalls and proxy servers may block uncommon protocols and ports, which may prevent the application from working correctly in some scenarios where security policies prevent access to
uncommon protocols and ports.
- When communicating with business layers, services, and components on a remote physical tier, use a message-based protocol when possible.
- When communicating with business layers, services, and components on a remote physical tier, use coarse-grained interfaces to minimize network traffic and maximize performance.
- Use asynchronous calls to a remote business layer using service methods when possible, especially where the calls must pass across physical tier boundaries.
- Where practical, enable offline processing for the application by detecting the connection state, caching information locally, and then re-synchronizing when communication is re-enabled. This may also require the application to hold state information and
data locally in a persistent cache to enable the application to start up when not connected, and to survive a restart without losing information.
- Identify security requirements for communication. Data passed to remote business layers and services may be vulnerable to interception and tampering. To protect sensitive information and communication channels, consider using IPSec to secure the channel,
and SSL to protect the data.
- Consider encrypting the data passed across the channel using strong encryption techniques, and even the use of digital signatures to detect tampering with the message content.
- When choosing communication protocols, consider the performance and network impact if the application must consume or send large sets of data. Consider using compression mechanisms to minimize the data payload size for message-based protocols such as SMTP
- Consider custom binary formats when the application does not have to support open communication standards.
Complex user interfaces are common in business applications. Users may open several forms to perform common tasks, and work with data in a range of different ways. To maximize extensibility and maintenance of the application, consider implementing the interface
using the Composition design pattern, where the UI consists of separate modules or forms loaded dynamically at runtime. Users can open and close forms as required, and the application can maximize performance and reduce start-up delays by loading these forms
only when required. Also consider how you can support personalization for users, so that they can modify the layout and content to suit their own requirements.
When designing a composition strategy, consider the following guidelines:
- Identify the types of interface components you require. These may be Windows Forms, WPF Forms, Office-style documents, user controls, or custom modules. Also decide whether you need menus, navigation bars, toolbars, and other interface components.
- Identify an appropriate composition mechanism. You may decide to use a composition framework or built-in features of your development environment such as user controls or document panels. The p&p Composite Application Guidance for WPF can help you split
the development of your WPF client application across multiple development teams and seamlessly compose the pieces.
- Identify the navigation strategy you require, such as menus or hyperlinks in navigation bars. Design these to be as intuitive as possible, and maintain a consistent appearance across all interface components to avoid confusing the user.
- Determine how you will manage versioning of the UI components, and how you will update them when new versions are available. By dynamically loading models, you reduce the impact of changes and allow individual modules to be updated as required.
Rich Client applications will usually require configuration information loaded at start-up, and sometimes during execution. This information may be network or connection information, user settings, part of the UI business rules, or general display and layout
settings. You may decide to store some or all of this information locally, or download it from other layers when the application starts. You may also need to persist changes to the information as the application runs or when it ends; for example, storing user
preferences, layout settings, and other UI data in a user's local profile.
When designing a configuration management strategy, consider the following guidelines:
- Determine what information you need to store in configuration.
- Choose the storage location, whether it should be stored locally or retrieved from elsewhere within the application layers.
- Determine if you need to cache configuration information locally, and – if so – where and how to implement this caching. You may decide to use the user's profile store, a locally installed database (such as SQL Server Express or SQL Server Compact Edition),
the file system, a framework such as the Enterprise Library Caching Application Block, or a custom mechanism. Alternatively, you may decide to store the information in code variables, or in an in-memory cache such as "Velocity", if it is not necessary
to maintain a local persistent copy.
- Identify sensitive configuration information, and implement a suitable mechanism for protecting it during transit over the network, when persisted locally, and even when stored in memory. Consider encrypting stored configuration information, and removing
it from the cache when no longer required.
- When using Windows application configuration files, take advantage of the capabilities for encrypting sections of the file.
- Take into account any security policies that affect configuration and caching, and ensure that the application applies Group Policy overrides to configuration information. This is a requirement to obtain Windows Certification for an application, and should
be a requirement of all your business applications.
Rich Client applications will usually access data stored on a remote physical tier, as well as data stored on local physical layers and even on the local machine. Data access often has a significant impact on performance, and is the most obvious factor in the
user's perception of an application and its usability and responsiveness. You should aim to maximize performance of data access routines and data transmission across tiers. You must also design the application with regard to the types of data it will use,
and the way that this data is exposed from other layers of the application.
When designing a data services strategy, consider the following guidelines:
- If you are using Domain Model, expose data as custom entities and collections of entities.
- If you are using a database-driven model, expose data as native .NET data types such as DataSets and DataTables, or typed DataSets.
- If the client application cannot handle the data in the exposed format you must implement a translation mechanism that converts it, but this will have an impact on performance.
- Consider existing frameworks and tools, like Enterprise Library Data Access Application Block, that can reduce development time and effort for general data access scenarios. .
- If the client will consume very large data sets, consider chunking these and loading them asynchronously into a local cache to improve performance. Determine how to handle inconsistencies between the local copy and the original data.
- Whenever possible, load data asynchronously so that the user interface is still interactive while the data is loading. However, you must also be aware of conflicts that may occur if the user attempts to interact with the data before loading is complete,
and design the interface to protect against errors arising from this.
- Implement a service dispatcher mechanism to support batch processing and allow users to perform multiple updates to data. You may also need to implement a mechanism to monitor connectivity, and – where appropriate – send batched updates when a suitable
connection is available.
- Determine how you will detect and manage concurrency conflicts that arise when these users attempt to update the data store. You may consider, for example, assigning clients that add data to the data store with different sets of temporary values to use
as primary keys for data items, and then setting the actual key only when the update takes place to avoid duplicate key errors.
- Consider how you will detect conflicts caused by locally cached data, and how you will resolve them. You may decide to resolve conflicts based on a set of rules that determine user precedence, or implement a conflict resolution mechanism with a UI that
allows users to manually resolve conflicts. In all cases, you must implement a mechanism that notifies users of update conflicts.
All applications and services are subject to the occurrence of errors and exceptions, and you must implement a suitable strategy for detecting and managing these errors and exceptions. In a Rich Client application, you will usually need to notify the user.
In addition, for anything other than trivial UI errors such as validation messages, you should implement a mechanism that logs errors and exceptions, notifies administrators, and exposes information for use by management tools and monitoring systems.
When designing an exception management strategy, consider the following guidelines:
- Identify the errors and exceptions likely to arise in the application, and which of these require only user notification. Errors such as validation failures are usually only notified locally to the user. However, errors such as repeated invalid logon attempts
or detection of malicious data should be logged and administrators notified. All execution exceptions and application failures should be logged and administrators notified.
- Identify an overall strategy for handling exceptions. This may involve actions such as wrapping exceptions with other application-specific or custom exceptions that contain additional data to assist in resolving failures, or replacing exceptions to prevent
exposure of sensitive information. Also implement a mechanism for detecting unhandled exceptions and logging these. A framework for managing exceptions may be useful for these tasks. The Enterprise Library Exception Management Application Block provides a
suitable set of features.
- Determine how you will store exception information, how you will pass it to other layers of the application if required, and how you will notify administrators. Consider using a monitoring tool or environment that can read events from the local Event Log
and present a view of the application state to administrators. Other technologies such as SNMP and WMI are useful tools that administrators often use, and you may consider publishing exception details through these mechanisms.
- Ensure that you sanitize exception information that is exposed to users to prevent sensitive information being displayed or stored in log and audit files. If necessary, encrypt information and use secure channels to communicate exceptions and errors to
other physical tiers of the application.
Rich Clients, whether designed to run offline or only when connected, will generally store state information. This may include user settings, configuration information, workflow information, business rule values, and data that the UI is displaying and the user
is editing. The application must be able to cache this data, access it as required, and handle conflicts, restarts, and connection status changes.
When designing a state management strategy, consider the following guidelines:
- Determine the state information that the application must cache, including estimations of the size, the frequency of changes, and the processing or overhead cost of recreating or re-fetching the data. These factors will help you to decide what type of cache
mechanism to use.
- Identify state that is applicable to the whole application, and state that is applicable to individual users or all users in a specific role.
- If you have large volumes of data, consider using a local disk-based caching mechanism.
- If the data changes regularly, and is easy to recreate or re-fetch, do not cache it unless it is very small – and then cache it only in memory or in code variables.
- If the data does not change regularly, for example user's preferences or the configuration settings for the application, cache it in memory to improve performance unless the volume of the data is very large.
- If the application requires data to be available when it starts up, use a persistent caching mechanism such as Isolated Storage or a disk file.
- If the cache contains large amounts of data that must be retrieved from another physical tier, and is not all required when the application starts up, consider asynchronous cache loading.
- When caching sensitive data, ensure that you implement the appropriate level of protection through encryption and/or digital signatures.
- Consider how and when you will remove items from the cache. If the data is no longer required, remove it from the cache. This is especially important when using an in-memory cache because the application will usually benefit from the increase in available
- In some cases, you may need to incorporate state changes into a transaction, such as when updating a data source with data edited by the user. Identify this requirement and implement a suitable transactional mechanism and commit/rollback functionality.
Some Rich Client applications require viewflow or workflow support to enable multi-stage operations or Wizard-style UI elements. You can implement these features using separate components, custom solutions, or take advantage of a framework such as Windows Workflow
(WF) or, for document-based interfaces, Microsoft Office SharePoint Server (MOSS).
When designing a workflow strategy, consider the following guidelines:
- Identify the workflow or viewflow requirements of your application.
- For simple workflow and viewflow requirements, it is usually sufficient to implement them using custom code based on well-known patterns such as Use Case Controller and ViewFlow.
- For more complex workflow and viewflow requirements, determine if any existing frameworks are suitable. Consider Windows Workflow (WF) for code-based workflow tasks or custom viewflows. Consider Microsoft Office SharePoint Server (MOSS) for document-based
- Consider creating separate components to implement your workflow and viewflow tasks. This reduces dependencies and makes it easier to swap out components as requirements change.
- Consider how you will capture, manage, and display errors in workflows. Identify how you will handle part-completed tasks, and whether it is possible to recover from a failure and continue the task or whether you need to restart the process.
Rich Client applications often implement the presentation layer for business applications. They are the part of the application that the user sees and interacts with, and must therefore satisfy many requirements. These requirements encompass general factors
such as usability, performance, design, and interactivity. A poor user interface can negatively impact on a business application that performs well in all other aspects.
When designing the presentation features of you application, consider the following guidelines:
- Analyze user and business application requirements thoroughly to ensure that the UI implements all the required capabilities. Failing to identify a requirement prior to implementation can result in an unusable or impractical interface, and require major
modification to the application later on.
- Decide if you need to create workflows or viewflows to implement multi-step Wizard-style interface elements. Often you will create separate components to implement these features, or make use of a workflow engine. Examples of workflow engines are Windows
Workflow (WF) and, for document-based interfaces, Microsoft Office SharePoint Server (MOSS).
- Investigate how you can separate data used by the UI, which may be cached or stored locally, from the UI itself. This makes it easier to update parts of the application, allows developers and designers to work separately on the components, and improves
- Take advantage of data binding capabilities to display data whenever possible, especially for tabular and multi-row data presentation. This reduces the code required, simplifies development, and reduces coding errors. It can also automatically synchronize
data in different views or forms. Use two-way binding where the user must be able to update the data.
- Consider how you will display documents in an Office document-style interface, or when displaying document content or HTML in other UI elements. Ensure that the user is protected from invalid and malicious content that may reside in documents.
- Implement command and navigation strategies and mechanisms that are flexible and can be updated easily. Consider implementing well-known design patterns such as Command, Publish/Subscribe, and Observer to decouple commands and navigation from the components
in the application and improve testability.
- Ensure that you implement features that maximize usability. For example, follow the common guidelines for UI design, navigation paths, content and control layout, and control types (such as the choice of appropriate list and option button controls) to avoid
- Ensure that you implement features that maximize accessibility. You must follow accessibility guidelines for users with a range of disabilities. Development environments often contain features that assist in creating accessible applications and can help
to locate areas of non-compliance. Visual Studio provides such features for Windows Forms and WPF applications.
- Ensure that the application can be globalized and localized to all geographical and cultural scenarios where it may be used. This includes changing the language, text direction, and content layout based on configuration or auto-detection of the user's
- Consider the display, input, and processing limitations of the target device or system. These limitations may include screen size and resolution, the capability to display colors and rich media, the lack of a keyboard, and the use of touch screens or pen
and ink input.
- Consider exposing interfaces that allow other applications or services to access and collect details such as reporting information, notifications, and performance data.
- Consider how the UI will appear and perform when disconnected if this is a scenario you must support.
Business/Service Layer Considerations
Rich Client applications will, in most business scenarios, access data or information located outside the application. While the nature of the information will vary, it is likely to be extracted from a business system. The Rich Client application may act as
the presentation layer for the business application, or may include a business layer, data access layer, and service agents that communicate with remote services. You should design the Rich Client interface using the accepted principles for designing presentation
layers. In addition, to maximize performance and usability, you may consider locating some of the business processing tasks on the client.
When designing interaction with business and service layers, consider the following guidelines:
- Identify the business layers and service interfaces that the application will use. Import the interface definitions and write code that accesses the business layer service functions against the interface to minimize coupling between the client and the business
layer and services.
- If your business logic does not contain sensitive information, consider locating some of the business rules on the client to improve performance of the UI and the client application.
- If your business logic does contain sensitive information then you should move the business layer to a separate tier.
- Consider how the client will obtain information required to operate business rules and other client-side processing, and how it will update the business rules automatically as requirements change. You may wish to have the client obtain business rule information
from the business layer when it starts up.
It is vital to minimize maintenance cost and effort for all applications and components. Rich Client applications are usually located remotely from the main servers of an application, and are subsequently more difficult to maintain than locally-installed services
and components. You should implement mechanisms that reduce maintenance liabilities. The issues to consider include deployment, updates, patches, and versioning.
When designing a maintainability strategy, consider the following guidelines:
- Implement a suitable mechanism for manual and/or automatic updates to the application and its components. You must take into account versioning issues to ensure that the application has consistent and interoperable versions of all the components it uses.
- Investigate the appropriate deployment options. Depending on the presentation technology used, these may include ClickOnce, Windows Installer, and XCOPY.
- Design the application so that components are interchangeable where possible, allowing you to change individual components depending on requirements, runtime scenarios, and individual user requirements or preferences.
- Implement logging and auditing as appropriate for the application to assist administrators and developers when debugging the application and solving runtime problems.
- Design to minimize dependencies between components and layers so that the application can be used in different scenarios where appropriate, and to reduce the possibility of changes to other layers affecting the client application.
- Investigate the use of frameworks and libraries of components that can reduce development time and increase maintainability. For example, the Composite Application Guidance for WPF makes it easy to swap out components without requiring changes to the core
- Investigate the use of a central application installation, configuration, and update environment. An example is Microsoft System Center Configuration Manager.
Security encompasses a range of factors and is vital in all types of applications. Rich Client applications must be designed and implemented to maximize security issues, and – where they act as the presentation layer for business applications – must play their
part in protecting and securing the other layers of the application. Security issues involve a range of concerns, including protecting sensitive data, user authentication and authorization, guarding against attack from malicious code and users, and auditing
and logging events and user activity.
When designing a security strategy, consider the following guidelines:
- Investigate and catalog the security risks the application faces from malicious users and code, execution errors and exceptions, lack of appropriate data and information protection, and other types of attack. A common approach is to create a threat model
that attempts to identify each risk and assign a relative value for the likelihood and the overall impact of a successful attack.
- Create a security policy, or incorporate the presentation UI and Rich Client security policies into an overall application or company security policy. The results of risk assessments and threat models will help you to specify a suitable policy. It can set
out rules for how you handle security-related tasks or vulnerable information, including the techniques to use for authentication and authorization, user management, configuration, secure communication, physical and logical location of data and business rules,
network security infrastructure requirements, and more.
- Determine your authorization strategy, and identify how user identity will flow to backend services. You may wish to use resource-based authorization so that users access the other layers of the application using their individual logon identity. Alternatively,
you may choose role-based authorization where users are assigned to one or more roles and access resources within the context of that role. Decide whether to perform this role mapping on the client or further down the application layer stack.
- If you choose role-based authentication and decide to map the users to their respective roles on the client, decide which type of store, such as a database, Active Directory, or a custom implementation, that you will use for user-to-role mappings. Take
into account the requirements for disconnected or offline role-mapping where this is relevant.
- Determine the appropriate technology and approach for authenticating users, including support for multiple users for the same Rich Client application instance. You should consider how and when to log on users, whether you need to support different types
of users (different roles) with differing permissions (such as administrators and standard users), and how you will record successful and failed logons. Take into account the requirements for disconnected or offline authentication where this is relevant.
- Consider a Single-Sign-On (SSO) or federated authentication solution if users must be able to access multiple applications with the same credentials or identity. You can implement a suitable solution by registering with an external agency that offers federated
authentication, use certificate systems, or create a custom solution for your organization.
- Consider the need to validate inputs, both from the user and from sources such as services and other application interfaces. You may need to create custom validation mechanisms, or you may be able to take advantage of validation frameworks. Visual Studio
Windows Forms development environment contains validation controls. The Enterprise Library Validation Application Block provides comprehensive features for validation in the UI and in the business layer. Irrespective of your validation choice, remember that
you must always validate data when it arrives at other layers of the application.
- Consider how you will protect data stored in the application and in resources such as files, caches, and documents used by the application. Encrypt sensitive data where it may be exposed, and consider using a digital signature to prevent tampering. In maximum
security applications, consider encrypting volatile information stored in memory. Also remember to protect sensitive information that is sent from the application over a network or communication channel.
- Consider how you will implement auditing and logging for the application, and what information to include in these logs. Remember to protect sensitive information in the logs using encryption, and optionally use digital signatures for the most sensitive
types of information that is vulnerable to tampering.
- Consider if you need to protect application code and other information such as configuration data and business rules. You can use obfustication techniques, or more robust encryption if required.
Data Handling Considerations
Application data can be made available from server-side applications through a Web service. Cache this data on client to improve performance and enable offline usage.
Rich Client applications can also use local data.
Types of Data
- Read-Only Reference Data: Data that is not changed by the client, and is used by the client for reference purposes. Store reference data on the client to reduce the amount of data interchange between the client and the server to improve the performance
of your application, enable offline capabilities, provide early data validation, and generally improve the usability of your application. There is no need to keep track of client-side changes to the data.
- Transient data: Data that is changed on the client as well as the on server. One of the most challenging aspects of dealing with transient data on smart clients is that it can generally be modified by multiple clients at the same time. You must keep
track of any client-side changes made to transient data on the client.
Rich Clients often need to cache data locally, whether it is read-only reference data or transient data. Caching data can improve performance in your application and provide the data necessary to work offline.** To enable data caching, Rich Client applications
should implement some form of caching infrastructure that can handle the data caching details transparently.
- Short-term data caching: Data is not persistent, so the application cannot run offline.
- Long-term data caching: Caching data in a persistent medium, such as isolated storage or the local file system, allows the application to work when there is no connectivity to the server. Rich Client applications should differentiate between data
that has been successfully synchronized with the server and data that is still tentative.
Changes to the data held on the server can occur before any client-side changes are synchronized with the server. You must implement a mechanism to ensure that any data conflicts are handled appropriately when the data is synchronized, and the resulting data
is consistent and correct.
Approaches for handling data concurrency:
- Pessimistic concurrency. Pessimistic concurrency allows one client to maintain a lock over the data to prevent any other clients from modifying the data until the client’s own changes are complete.
- Optimistic concurrency. Optimistic concurrency does not lock the data. The original data is then checked against the current data to see if it has been updated in the meantime.
Using ADO.NET DataSets to Manage Data
The ADO.NET DataSet helps clients to work with data while offline. They can keep track of local changes made to the data, which makes it easier to synchronize the data with the server and reconcile data conflicts. Data Sets can also be used to merge data from
Windows Forms Data Binding
Windows Forms data binding supports bi-directional binding that allows you to bind a data structure to a user interface component, display the current data values to the user, allows the user to edit the data, and then updates the underlying data automatically
with the values entered by the user.
Data binding can be used to:
- Display read-only data to users.
- Allow users to update data within the user interface.
- Provide master-detail views on data.
- Allow users to explore complex related data items.
- Provide lookup table functionality, allowing the user interface to connect user-friendly display names.
- You should implement custom formatting within the form that is responsible for presenting the data in a specific format, and then associate the validation rules with the data itself so that the rules can be reused across multiple forms.
- The data itself is encapsulated in a model object.
- The view object is the Windows Forms control that the data is bound to.
- The controller object provides a natural location for validating changes made to the data, and all user interface validation logic should be implemented here.
Offline / Occasionally Connected Considerations
An application is occasionally connected if, during unspecified periods, it cannot interact with services or data over a network in a timely manner. Occasionally connected Rich Client applications are capable of performing work when not connected to a network
resource, and can update the network resources in the background when a connection is available.
Offline / Occasionally Connected Design Strategies:
- Data-centric: Applications that use the data-centric strategy have a relational database management system (RDBMS) installed locally on the client, and use the built-in capabilities of the database system to propagate local data changes back to the
server, handle the synchronization process, and detect and resolve any data conflicts.
- Service-oriented: Applications that use the service-oriented approach store information in messages and arrange those messages in queues while the client is offline. After the connection is reestablished, the queued messages are sent to the server
Principles of Occasionally Connected Applications
- Favor asynchronous communication. Favor asynchronous communication when interacting with data and services on network.
- Minimize complex network interactions. Minimize or eliminate complex interactions with network-located data and services.
- Add data caching capabilities. Your application must ensure that all of the data necessary for the user to continue working is available on the client when it goes offline.
- Manage connections. You should consider the environment in which your application operates, both in terms of the available connectivity and the desired behavior of your application as this connectivity changes. Your application can be designed to function
when the user decides to work offline.
- Design a store-and-forward mechanism. In a store-and-forward mechanism, messages are created, stored, and eventually forwarded to their respective destinations. The most common implementation of store-and-forward is the message queue.
- Determine how to deal with stale data and how to prevent your smart clients from using stale data.
With a rich client there are several options for deployment. You might have a stand-alone application where all of the application logic including data is deployed to the client. Another option would be client-server where the application logic is deployed
on the client and data is deployed to a database tier. Finally, there are several n-tier options where an application server contains part of the application logic.
The following diagram illustrates a stand-alone deployment where all of the application logic and data are deployed to the client.
With a client-server deployment all of the application logic is deployed to the client and the data is deployed to a database server.
With an n-tier deployment you can place presentation and business logic on the client, or just the presentation logic on the client. This first diagram illustrates and option where the presentation and business logic is deployed to the client.
This next diagram illustrates an option where the business and data access logic are deployed to an application server.
Deploying Rich Client Applications
When it comes to deploying the rich client application to a physical machine there are several options available.
- No-Touch Deployment.
- No-Touch Deployment with an application update stub.
- XCOPY Deployment.
- Windows Installer Packages.
- XBAP (XML Browser Application).
- Know your target physical deployment environment early, from the planning stage of the lifecycle.
- Clearly communicate what environmental constraints drive software design and architecture decisions.
- Clearly communicate what software design decisions require certain infrastructure attributes.
Platform Security Guidelines:
- Install the appropriate patches and updates.
- Disable unnecessary services and protocols.
- Apply the appropriate account policies, and disable unnecessary accounts.
- Set appropriate permissions on files, directories, shares, and resources.
- Close unused ports.
- Secure the Windows Registry.
- Using auditing and logging to detect problems and intrusions.
||Inversion of Control
||Gateway / Service Gateway
||Service Agent and Proxy
||Chain of Responsibility
||Event Broker, Publish/Subscribe
||Model View Controller
||Service to Worker
- Asynchronous Callback. Execute all long running non-UI related tasks on a separate thread.
- Composite View. Combine individual views into a composite view
- Layered Architecture. Logically group components that perform similar type of functions into layers.
- Model View Controller. Separate the user interface, the data repository features, and the code logic that binds the two together.
- Supervising Controller. Consolidate all requests handling by channeling them through a single handler object, which can be modified at runtime with decorators.
- Template View. Implement a common template view, derive or construct views using the template view.
- If you need good performance, interactivity, and design support in Visual Studio, use Windows Forms.
- If your application requires islands of rich media support, use Windows Forms combined with WPF User Controls.
- If your application must be highly graphical and support rich media and presentation features, use WPF.
- If you need to build composite interfaces using Windows Forms, consider the Smart Client Software Factory.
- If you need to build composite interfaces using WPF, consider the Composite Application Guidance.
- If your application will be downloaded from a Web server and then execute on the client, use XAML Browser Applications (XBAP).
- If your application is predominantly document-based or used for reporting, use and OBA with Office document automation (such as InfoPath, Excel, or Word).
patterns & practices Solution Assets
- The Composite Application Guidance for WPF can help you split the development of your WPF client application across multiple development teams and seamlessly compose the pieces. For more information, see
- Enterprise Library provides a series of application blocks that simplify common tasks such as caching, exception handling, validation, logging, cryptography, credential management, and facilities for implementing design patterns such as Inversion
of Control and Dependency Injection. For more information, see
- Unity Application Block is a lightweight, extensible dependency injection container that helps you to build loosely coupled applications. For more information, see
- Smart Client Software Factory helps you to incorporate many of the proven practices and patterns for building composite Rich Client applications. For more information, see