WCF Refresher

I’ve just read the book Programming WCF Services by Juval Lowy and Michael Montgomery. It’s a thorough book that has a lot of detailed information on different aspects of WCF, like instance management, handing of the faults, transactions, concurrency management, security, etc. Here is my WCF refresher composed from this book that contains possible options for the major configurations, preferred choices in different cases, WCF coding standards, etc.

WCF Essentials

Choosing a host for an Internet service:
Choosing a host for an Internet service

Choosing a host for an intranet service:
Choosing a host for an intranet service:

Transport and encoding for common bindings:
Transport and encoding for common bindings

Choosing a binding:
Choosing a binding

The WCF host architecture:
The WCF host architecture

Reliability and ordered delivery:
Reliability and ordered delivery

Instance Management

Instance mode of the service is configured by InstanceContextMode property of ServiceBehavior attribute.

Possible values are:

Example of configuration:

Per-call services are the preferred instance management mode for most WCF services.

Transport session mode of the service is configured by SessionMode property of ServiceContract attribute.

Possible values are:

Example of configuration:

Instance mode as a product of the binding, contract configuration, and service behavior:
Instance mode as a product of the binding, contract configuration, and service behavior

Transactions

Client’s transaction flows into the service is configured by TransactionFlow attribute on operation level.

Possible values are:

Example of configuration:

Presence of ambient transaction for service operation is configured by TransactionScopeRequired property of the OperationBehavior attribute. The default value is false, that is why by default service has no ambient transaction.

Example of configuration:

Transaction propagation as the product of contract, binding, and operation behavior:
Transaction propagation as the product of contract, binding, and operation behavior

Transaction modes as the product of binding, contract, and behavior:
Transaction modes as the product of binding, contract, and behavior

Preferred transaction modes are Client/Service and Client.

Recommended instancing modes, configurations, and transactions:
Recommended instancing modes, configurations, and transactions

Concurrency mode

Concurrent access to the service instance is configured by the ConcurrencyMode property of the ServiceBehavior attribute.

Possible values are:

Example of configuration:

Security

Bindings and transfer security modes:
Bindings and transfer security modes

Bindings and Transport security client credentials:
Bindings and Transport security client credentials

Bindings and Message security client credentials:
Bindings and Message security client credentials

Bindings and security scenarios:
Bindings and security scenarios

Security aspects of the various scenarios:
Security aspects of the various scenarios

Tools

WCF-Provided Test Host
Visual Studio ships with test service host suitable for development needs. It could be found under “c:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\WcfSvcHost.exe”.

Example of usage:
WcfSvcHost.exe /service:MyService.dll /config:App.config

WCF-Provided Test Client
Visual Studio ships with test WCF client suitable for development needs. It could be found under “c:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\WcfTestClient.exe”.
WCF-Provided Test Client

SvcConfigEditor
WCF provides config file editor for both server and client configuration. It could be found under "c:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\SvcConfigEditor.exe"
SvcConfigEditor

WCF Coding Standard

Here are suggested WCF coding rules and best practices, listed in Appendix F of the book.

General Design Guidelines
1. All services must adhere to these principles:
a. Services are secure.
b. Service operations leave the system in a consistent state.
c. Services are thread-safe and can be accessed by concurrent clients.
d. Services are reliable.
e. Services are robust.

2. Services can optionally adhere to these principles:
a. Services are interoperable.
b. Services are scale-invariant.
c. Services are available.
d. Services are responsive.
e. Services are disciplined and do not block their clients for long.

Essentials
1. Place service code in a class library, not in any hosting EXE.
2. Do not provide parameterized constructors to a service class, unless it is a singleton that is hosted explicitly.
3. Enable reliability in the relevant bindings.
4. Provide a meaningful namespace for contracts. For outward-facing services, use your company’s URL or equivalent URN with a year and month to support versioning.
For example:

For intranet services, use any meaningful unique name, such as MyApplication. For example:

5. With intranet applications, prefer self-hosting to IIS hosting when the WAS is unavailable.
6. Do not mix and match named bindings with default bindings. Either have all your bindings be explicitly referenced, or use only default bindings.
7. Do not mix and match named behaviors with default behaviors. Either have all your behaviors be explicitly referenced, or use only default behaviors.
8. Always name all endpoints in the client config file.
9. Do not use SvcUtil or Visual Studio to generate a config file.
10. When using a tool such as Visual Studio to generate the proxy, do clean up the proxy.
11. Do not duplicate proxy code. If two or more clients use the same contract, factor the proxy to a separate class library.
12. Always close or dispose of the proxy.
13. When using discovery, prefer dynamic addresses.
14. When using discovery, do support the metadata exchange endpoint over TCP.
15. When using discovery, avoid cardinality of “some”.

Service Contracts
1. Always apply the ServiceContract attribute on an interface, not a class:

2. Prefix the service contract name with an I:

3. Avoid property-like operations:

4. Avoid contracts with one member.
5. Strive to have three to five members per service contract.
6. Do not have more than 20 members per service contract. Twelve is probably the practical limit.

Data Contracts
1. Avoid inferred data contracts (POCO). Instead, be explicit and apply the DataContract attribute.
2. Use the DataMember attribute only on properties or read-only public members.
3. Avoid explicit XML serialization on your own types.
4. Avoid message contracts.
5. When using the Order property, assign the same value to all members coming from the same level in the class hierarchy.
6. Support IExtensibleDataObject on your data contracts. Use explicit interface implementation.
7. Avoid setting IgnoreExtensionDataObject to true in the ServiceBehavior and CallbackBehavior attributes. Keep the default of false.
8. Do not mark delegates and events as data members.
9. Do not pass .NET-specific types, such as Type, as operation parameters.
10. Handle known types using the generic resolver.
11. Suppress the generation of a generic type parameter hash code and provide a legible type name instead.

Instance Management
1. Prefer the per-call instance mode when scalability is a concern.
2. If setting SessionMode.NotAllowed on the contract, always configure the service instancing mode as InstanceContextMode.PerCall.
3. Do not mix sessionful contracts and sessionless contracts in the same service.
4. Avoid a singleton unless you have a natural singleton.
5. Use ordered delivery with a sessionful service.
6. Avoid instance deactivation with a sessionful service.
7. Avoid demarcating operations.
8. With durable services, always designate a completing operation.

Operations and Calls
1. Do not treat one-way calls as asynchronous calls.
2. Do not treat one-way calls as concurrent calls.
3. Expect exceptions from a one-way operation.
4. Enable reliability even on one-way calls. Use of ordered delivery is optional for one-way calls.
5. Avoid one-way operations on a sessionful service. If used, make it the terminating operation:

6. Name the callback contract on the service side after the service contract name, suffixed by Callback:

7. Strive to mark callback operations as one-way.
8. Use callback contracts for callbacks only.
9. Avoid mixing regular callbacks and events on the same callback contract.
10. Event operations should be well designed:
a. void return type
b. No out-parameters
c. Marked as one-way operations
11. Avoid using raw callback contracts for event management, and prefer using the publish-subscribe framework.
12. Always provide explicit methods for callback setup and teardown:

Faults
1. Never use a proxy instance after an exception, even if you catch that exception.
2. Do not use the using statement on a proxy.
3. Avoid fault contracts and allow WCF to mask the error.
4. Do not reuse the callback channel after an exception even if you catch that exception, as the channel may be faulted.
5. Use the FaultContract attribute with exception classes, as opposed to mere serializable types:

6. Avoid lengthy processing such as logging in IErrorHandler.ProvideFault().
7. With both service classes and callback classes, set IncludeExceptionDetailInFaults to true in debug sessions, either in the config file or programmatically:

8. In release builds, do not return unknown exceptions as faults except in diagnostic scenarios.

Transactions
1. Never manage transactions directly.
2. Apply the TransactionFlow attribute on the contract, not the service class.
3. Do not perform transactional work in the service constructor.
4. Using this book’s terminology, configure services for either Client or Client/Service transactions. Avoid None or Service transactions.
5. Using this book’s terminology, configure callbacks for either Service or Service/Callback transactions. Avoid None or Callback transactions.
6. When using the Client/Service or Service/Callback mode, constrain the binding to flow transactions using the BindingRequirement attribute.
7. On the client, always catch all exceptions thrown by a service configured for None or Service transactions.
8. Enable reliability and ordered delivery even when using transactions.
9. In a service operation, never catch an exception and manually abort the transaction:

10. If you catch an exception in a transactional operation, always rethrow it or another exception.
11. Keep transactions short.
12. Always use the default isolation level of IsolationLevel.Serializable.
13. Do not call one-way operations from within a transaction.
14. Do not call nontransactional services from within a transaction.
15. Do not access nontransactional resources (such as the filesystem) from within a transaction.
16. With a sessionful service, avoid equating the session boundary with the transaction boundary by relying on auto-complete on session close.
17. When using a sessionful or transactional singleton, use volatile resource managers to manage state and avoid explicitly state-aware programming or relying on WCF’s instance deactivation on completion.
18. With transactional durable services, always propagate the transaction to the store by setting SaveStateInOperationTransaction to true.

Concurrency Management
1. Always provide thread-safe access to:
a. Service in-memory state with sessionful or singleton services
b. Client in-memory state during callbacks
c. Shared resources
d. Static variables
2. Prefer ConcurrencyMode.Single (the default). It enables transactional access and provides thread safety without any effort.
3. Keep operations on single-mode sessionful and singleton services short in order to avoid blocking other clients for long.
4. When you are using ConcurrencyMode.Multiple, you must use transaction autocompletion.
5. Consider using ConcurrencyMode.Multiple on per-call services to allow concurrent calls.
6. Transactional singleton service with ConcurrencyMode.Multiple must have ReleaseServiceInstanceOnTransactionComplete set to false:

7. Never self-host on a UI thread, and have the UI application call the service.
8. Never allow callbacks to the UI application that called the service unless the callback posts the call using SynchronizationContext.Post().
9. When supplying the proxy with both synchronous and asynchronous methods, apply the FaultContract attribute only to synchronous methods.
10. Keep asynchronous operations short. Do not equate asynchronous calls with lengthy operations.
11. Do not mix transactions with asynchronous calls.

Queued Services
1. On the client, always verify that the queue (and a dead-letter queue, when applicable) is available before calling the queued service.
2. Always verify that the queue is available when hosting a queued service.
3. Except in isolated scenarios, avoid designing the same service to work both queued and non-queued.
4. The service should participate in the playback transaction.
5. When participating in the playback transaction, avoid lengthy processing in the queued service.
6. Avoid sessionful queued services.
7. When using a singleton queued service, use a volatile resource manager to manage the singleton state.
8. When using a per-call queued service, explicitly configure the contract and the service to be per-call and sessionless:

9. Always explicitly set contracts on a queued singleton to disallow sessions:

10. The client should call a queued service inside a transaction.
11. On the client side, do not store a queued service proxy in a member variable.
12. Avoid relatively short values of TimeToLive, as they negate the justification for a queued service.
13. Avoid nontransactional queues.
14. When using a response queue, have the service participate in the playback transaction and queue the response in that transaction.
15. Have the response service participate in the response playback transaction.
16. Avoid lengthy processing in a queued response operation.
17. With MSMQ 3.0, prefer a response service to a poison queue service dealing with failures of the service itself.
18. With MSMQ 4.0, use ReceiveErrorHandling.Reject for poison messages unless you have advanced processing with ReceiveErrorHandling.Move. Avoid ReceiveErrorHandling.Fault and ReceiveErrorHandling.Drop.
19. With MSMQ 4.0, consider the use of a response service to handle service playback failures.
20. Unless dealing with a sessionful contract and service, never assume the order of queued calls.
21. Avoid multiple service endpoints sharing a queue.
22. Avoid receive context.

Security
1. Always protect the message and provide for message confidentiality and integrity.
2. In an intranet, you can use Transport security as long as the protection level is set to EncryptAndSign.
3. In an intranet, avoid impersonation. Set the impersonation level to TokenImpersonationLevel.Identification.
4. When using impersonation, have the client use TokenImpersonationLevel.Impersonation.
5. Use the declarative security framework and avoid manual configuration.
6. Never apply the PrincipalPermission attribute directly on the service class:

7. Avoid sensitive work that requires authorization at the service constructor.
8. Avoid demanding a particular user, with or without demanding a role:

9. Do not rely on role-based security in the client’s callback operations.
10. With Internet clients, always use Message security.
11. Allow clients to negotiate the service certificate (the default).
12. Use the ASP.NET providers for custom credentials.
13. When developing a custom credentials store, develop it as a custom ASP.NET provider.
14. Validate certificates using peer trust.

This entry was posted in Books, Programming and tagged , , . Bookmark the permalink.

Leave a Reply