Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Tuesday, 6 July 2010

Ridiculous Microsoft - Visual Studio Extensions does not support 64-bit platform


SharePoint 2007 is decided to be used as content management server for our application. It gives us lots of troubles when customized web services are needed. For me I think customized web services are necessary for SharePoint 2007 unless you only use web browser as client. SharePoint exposes its interfaces by web services but it only exposes very limited interfaces in this way. No file check in or check out is supported!

Something also ridiculous to me is that a tool from MS, Visual Studio Extensions for WSS 3.0, does not support 64-bit platforms. This tool has to work with SharePoint server and all MSDN documents tell you that SharePoint server is better installed on 64-bit platform and it only supports 64-bit machine from SharePoint 2010.

Stupid MS.

Monday, 18 January 2010

InstanceContextMode and ConcurrencyMode

There are three InstanceContextMode in WCF.
  • PerCall: a new InstanceContext object is created and recycled succeeding each call.
  • PerSession: A new InstanceContext object is created per session and instance is not sharable by multiple sessions.
  • Single: A single instance is created and used for all incoming calls.
There are three ConcurrencyMode supported by WCF.
  • Single: The service instance is single threaded and does not accept reentrance calls. If a new message comes when another message is being processed, this message has to wait there until the first one is finished.
  • Multiple: The service is multi-threaded. It is fast. No waiting. But developer has to make sure the code is thread-safe.
  • Reentrance: The service is single threaded and can accept reentrant calls. It implies that the service processes only one message at a given time. To ensure thread safety, WCF locks the InstanceContext processing a message so that no other messages can be processed. In case of Reentrant mode, the InstanceContext is unlocked just before the service makes an outgoing call thereby allowing the subsequent call to get the lock next time it comes in to the service.
There are many factors we should think about when choosing service behavior.
  • Constructor of service. Probably InstanceConxt. Single should be used if there are lots of stuff to load and initialize. InstanceContext.PerSession should be used if there are states to maintain for one client. No thing to maintain for different calls, different clients, InstanceContext.PerCall should be used.
  • ConcurrencyMode does not matter if InstanceContextMode.PerCall is adopted. New available thread will be used if new call comes.
  • InstanceContext.PerCall and InstanceContext.PerSession mean same thing if there is no session maintained for this service
  • ConcurrencyMode.Reentrant does not mean multiple thread. It is single thread in most cases except there is outgoing service call.
  • Take care of thread-saftety if InstanceContextMode.Single and ConcurrencyMode.Multiple are considered to use. It will be faster and it will also be tricky.
We could put some logs to know when the object is initialized and which thread is used in the constructor. Just for confirmation.

Monday, 4 January 2010

OptimisticConcurrencyException-When it is triggered?

It could be triggered in two cases:
1)The entity property is defined in the conceptual layer with an attribute of ConcurrencyMode="fixed"(A property of Entity Framework, Not SQL Server).When this attribute is used, Object Services checks for changes in the database before saving changes to the database. Any conflicting changes will cause an OptimisticConcurrencyException.
By default, however, Object Services saves object changes to the database without checking for concurrency.

2)An OptimisticConcurrencyException can also occur when you define an Entity Data Model that uses stored procedures to make updates to the data source. In this case, the exception is raised when the stored procedure that is used to perform updates reports that zero rows were updated.

Wednesday, 2 December 2009

WCF Best Practices: Controlling Resource Consumption and Improving Performance

This article is from MSDN. Its address is http://msdn.microsoft.com/en-us/library/bb463275.aspx

Controlling Resource Consumption and Improving Performance

This topic describes various properties in different areas of the Windows Communication Foundation (WCF) architecture that work to control resource consumption and affect performance metrics.

Properties that Constrain Resource Consumption in WCF

Windows Communication Foundation (WCF) applies constraints on certain types of processes for either security or performance purposes. These constraints come in two main forms, either quotas and throttles. Quotas are limits that when reached or exceeded trigger an immediate exception at some point in the system. Throttles are limits that do not immediately cause an exception to be thrown. Instead, when a throttle limit is reached, processing continues but within the limits set by that throttle value. This limited processing might trigger an exception elsewhere, but this depends upon the application.

In addition to the distinction between quotas and throttles, some constraining properties are located at the serialization level, some at the transport level, and some at the application level. For example, the quota System.ServiceModel.Channels.TransportBindingElement.MaxReceivedMessageSize, which is implemented by all system-supplied transport binding elements, is set to 65,536 bytes by default to hinder malicious clients from engaging in denial-of-service attacks against a service by causing excessive memory consumption. (Typically, you can increase performance by lowering this value.)

An example of a serialization quota is the System.Runtime.Serialization.DataContractSerializer.MaxItemsInObjectGraph property, which specifies the maximum number of objects that the serializer serializes or deserializes in a single ReadObject method call. An example of an application-level throttle is the System.ServiceModel.Dispatcher.ServiceThrottle.MaxConcurrentSessions property, which by default restricts the number of concurrent sessionful channel connections to 10. (Unlike the quotas, if this throttle value is reached, the application continues processing but accepts no new sessionful channels, which means that new clients cannot connect until one of the other sessionful channels is ended.)

These controls are designed to provide an out-of-the-box mitigation against certain types of attacks or to improve performance metrics such as memory footprint, start-up time, and so on. However, depending on the application, these controls can impede service application performance or prevent the application from working at all. For example, an application designed to stream video can easily exceed the default System.ServiceModel.Channels.TransportBindingElement.MaxReceivedMessageSize property. This topic provides an overview of the various controls applied to applications at all levels of WCF, describes various ways to obtain more information about whether a setting is hindering your application, and describes ways to correct various problems. Most throttles and some quotas are available at the application level, even when the base property is a serialization or transport constraint. For example, you can set the System.Runtime.Serialization.DataContractSerializer.MaxItemsInObjectGraph property using the System.ServiceModel.ServiceBehaviorAttribute.MaxItemsInObjectGraph property on the service class.

Bb463275.note(en-us,VS.90).gifNote:
If you have a particular problem, you should first read the WCF Troubleshooting Quickstart to see whether your problem (and a solution) is listed there.

Properties that restrict serialization processes are listed in Security Considerations for Data. Properties that restrict the consumption of resources related to transports are listed in Transport Quotas. Properties that restrict the consumption of resources at the application layer are the members of the ServiceThrottle class.

Detecting Application and Performance Issues Related to Quota Settings

The defaults of the preceding values have been chosen to enable basic application functionality across a wide range of application types while providing basic protection against common security issues. However, different application designs might exceed one or more throttle settings although the application otherwise is secure and would work as designed. In these cases, you must identify which throttle values are being exceeded and at what level, and decide on the appropriate course of action to increase application throughput.

Typically, when writing the application and debugging it, you set the System.ServiceModel.Description.ServiceDebugBehavior.IncludeExceptionDetailInFaults property to true in the configuration file or programmatically. This instructs WCF to return service exception stack traces to the client application for viewing. This feature reports most application-level exceptions in such a way as to display which quota settings might be involved, if that is the problem.

Some exceptions happen at run time below the visibility of the application layer and are not returned using this mechanism, and they might not be handled by a custom System.ServiceModel.Dispatcher.IErrorHandler implementation. If you are in a development environment like Microsoft Visual Studio, most of these exceptions are displayed automatically. However, some exceptions can be masked by development environment settings such as the Just My Code settings in Visual Studio 2005.

Regardless of the capabilities of your development environment, you can use capabilities of WCF tracing and message logging to debug all exceptions and tune the performance of your applications. For more information, see Using Tracing to Troubleshoot Your Application.

Performance Issues and XmlSerializer

Services and client applications that use data types that are serializable using the XmlSerializer generate and compile serialization code for those data types at run time, which can result in slow start-up performance.

Bb463275.note(en-us,VS.90).gifNote:
Pre-generated serialization code can be used only in client applications and not in services.

The ServiceModel Metadata Utility Tool (Svcutil.exe) can improve start-up performance for these applications by generating the necessary serialization code from the compiled assemblies for the application. For more information, see How to: Improve the Startup Time of WCF Client Applications using the XmlSerializer.

Performance Issues When Hosting WCF Services Under ASP.NET

When a WCF service is hosted under IIS and ASP.NET, the configuration settings of IIS and ASP.NET can affect the throughput and memory footprint of the WCF service. For more information about ASP.NET performance, see http://msdn.microsoft.com/en-us/library/ms998549.aspx. One setting that might have unintended consequences is MinWorkerThreads, which is a property of the ProcessModelSection. If your application has a fixed or small number of clients, setting MinWorkerThreads to 2 might provide a throughput boost on a multiprocessor machine that has a CPU utilization close to 100%. This increase in performance comes with a cost: it will also cause an increase in memory usage, which could reduce scalability.

WCF Best Practices: Data Contract Versioning

This article is from MSDN. Its address is http://msdn.microsoft.com/en-us/library/ms733832.aspx

Best Practices: Data Contract Versioning

This topic lists the best practices for creating data contracts that can evolve easily over time. For more information about data contracts, see the topics in Using Data Contracts.

Note on Schema Validation

In discussing data contract versioning, it is important to note that the data contract schema exported by Windows Communication Foundation (WCF) does not have any versioning support, other than the fact that elements are marked as optional by default.

This means that even the most common versioning scenario, such as adding a new data member, cannot be implemented in a way that is seamless with regard to a given schema. The newer versions of a data contract (with a new data member, for example) do not validate using the old schema.

However, there are many scenarios in which strict schema compliance is not required. Many Web services platforms, including WCF and XML Web services created using ASP.NET, do not perform schema validation by default and therefore tolerate extra elements that are not described by the schema. When working with such platforms, many versioning scenarios are easier to implement.

Thus, there are two sets of data contract versioning guidelines: one set for scenarios where strict schema validity is important, and another set for scenarios when it is not.

Versioning When Schema Validation Is Required

If strict schema validity is required in all directions (new-to-old and old-to-new), data contracts should be considered immutable. If versioning is required, a new data contract should be created, with a different name or namespace, and the service contract using the data type should be versioned accordingly.

For example, a purchase order processing service contract named PoProcessing with a PostPurchaseOrder operation takes a parameter that conforms to a PurchaseOrder data contract. If the PurchaseOrder contract has to change, you must create a new data contract, that is, PurchaseOrder2, which includes the changes. You must then handle the versioning at the service contract level. For example, by creating a PostPurchaseOrder2 operation that takes the PurchaseOrder2 parameter, or by creating a PoProcessing2 service contract where the PostPurchaseOrder operation takes a PurchaseOrder2 data contract.

Note that changes in data contracts that are referenced by other data contracts also extend to the service model layer. For example, in the previous scenario the PurchaseOrder data contract does not need to change. However, it contains a data member of a Customer data contract, which in turn contained a data member of the Address data contract, which does need to be changed. In that case, you would need to create an Address2 data contract with the required changes, a Customer2 data contract that contains the Address2 data member, and a PurchaseOrder2 data contract that contains a Customer2 data member. As in the previous case, the service contract would have to be versioned as well.

Although in these examples names are changed (by appending a "2"), the recommendation is to change namespaces instead of names by appending new namespaces with a version number or a date. For example, the http://schemas.contoso.com/2005/05/21/PurchaseOrder data contract would change to the http://schemas.contoso.com/2005/10/14/PurchaseOrder data contract.

For more information, see Best Practices: Service Versioning.

Occasionally, you must guarantee strict schema compliance for messages sent by your application, but cannot rely on the incoming messages to be strictly schema-compliant. In this case, there is a danger that an incoming message might contain extraneous data. The extraneous values are stored and returned by WCF and thus results in schema-invalid messages being sent. To avoid this problem, the round-tripping feature should be turned off. There are two ways to do this.

For more information about round-tripping, see Forward-Compatible Data Contracts.

Versioning When Schema Validation Is Not Required

Strict schema compliance is rarely required. Many platforms tolerate extra elements not described by a schema. As long as this is tolerated, the full set of features described in Data Contract Versioning and Forward-Compatible Data Contracts can be used. The following guidelines are recommended.

Some of the guidelines must be followed exactly in order to send new versions of a type where an older one is expected or send an old one where the new one is expected. Other guidelines are not strictly required, but are listed here because they may be affected by the future of schema versioning.

  1. Do not attempt to version data contracts by type inheritance. To create later versions, either change the data contract on an existing type or create a new unrelated type.

  2. The use of inheritance together with data contracts is allowed, provided that inheritance is not used as a versioning mechanism and that certain rules are followed. If a type derives from a certain base type, do not make it derive from a different base type in a future version (unless it has the same data contract). There is one exception to this: you can insert a type into the hierarchy between a data contract type and its base type, but only if it does not contain data members with the same names as other members in any possible versions of the other types in the hierarchy. In general, using data members with the same names at different levels of the same inheritance hierarchy can lead to serious versioning problems and should be avoided.

  3. Starting with the first version of a data contract, always implement IExtensibleDataObject to enable round-tripping. For more information, see Forward-Compatible Data Contracts. If you have released one or more versions of a type without implementing this interface, implement it in the next version of the type.

  4. In later versions, do not change the data contract name or namespace. If changing the name or namespace of the type underlying the data contract, be sure to preserve the data contract name and namespace by using the appropriate mechanisms, such as the Name property of the DataContractAttribute. For more information about naming, see Data Contract Names.

  5. In later versions, do not change the names of any data members. If changing the name of the field, property, or event underlying the data member, use the Name property of the DataMemberAttribute to preserve the existing data member name.

  6. In later versions, do not change the type of any field, property, or event underlying a data member such that the resulting data contract for that data member changes. Keep in mind that interface types are equivalent to Object for the purposes of determining the expected data contract.

  7. In later versions, do not change the order of the existing data members by adjusting the Order property of the DataMemberAttribute attribute.

  8. In later versions, new data members can be added. They should always follow these rules:

    1. The IsRequired property should always be left at its default value of false.

    2. If a default value of null or zero for the member is unacceptable, a callback method should be provided using the OnDeserializingAttribute to provide a reasonable default in case the member is not present in the incoming stream. For more information about the callback, see Version-Tolerant Serialization Callbacks.

    3. The Order property on the DataMemberAttribute should be used to make sure that all of the newly added data members appear after the existing data members. The recommended way of doing this is as follows: None of the data members in the first version of the data contract should have their Order property set. All of the data members added in version 2 of the data contract should have their Order property set to 2. All of the data members added in version 3 of the data contract should have their Order set to 3, and so on. It is permissible to have more than one data member set to the same Order number.

  9. Do not remove data members in later versions, even if the IsRequired property was left at its default property of false in prior versions.

  10. Do not change the IsRequired property on any existing data members from version to version.

  11. For required data members (where IsRequired is true), do not change the EmitDefaultValue property from version to version.

  12. Do not attempt to create branched versioning hierarchies. That is, there should always be a path in at least one direction from any version to any other version using only the changes permitted by these guidelines.

    For example, if version 1 of a Person data contract contains only the Name data member, you should not create version 2a of the contract adding only the Age member and version 2b adding only the Address member. Going from 2a to 2b would involve removing Age and adding Address; going in the other direction would entail removing Address and adding Age. Removing members is not permitted by these guidelines.

  13. You should generally not create new subtypes of existing data contract types in a new version of your application. Likewise, you should not create new data contracts that are used in place of data members declared as Object or as interface types. Creating these new classes is allowed only when you know that you can add the new types to the known types list of all instances of your old application. For example, in version 1 of your application, you may have the LibraryItem data contract type with the Book and Newspaper data contract subtypes. LibraryItem would then have a known types list that contains Book and Newspaper. Suppose you now add a Magazine type in version 2 which is a subtype of LibraryItem. If you send a Magazine instance from version 2 to version 1, the Magazine data contract is not found in the list of known types and an exception is thrown.

  14. You should not add or remove enumeration members between versions. You should also not rename enumeration members, unless you use the Name property on the EnumMemberAttribute attribute to keep their names in the data contract model the same.

  15. Collections are interchangeable in the data contract model as described in Collection Types in Data Contracts. This allows for a great degree of flexibility. However, make sure that you do not inadvertently change a collection type in a non-interchangeable way from version to version. For example, do not change from a non-customized collection (that is, without the CollectionDataContractAttribute attribute) to a customized one or a customized collection to a non-customized one. Also, do not change the properties on the CollectionDataContractAttribute from version to version. The only allowed change is adding a Name or Namespace property if the underlying collection type's name or namespace has changed and you need to make its data contract name and namespace the same as in a previous version.

Some of the guidelines listed here can be safely ignored when special circumstances apply. Make sure you fully understand the serialization, deserialization, and schema mechanisms involved before deviating from the guidelines.

WCF Best Practices - Service Versioning

The following article is copied from MSDN.
Address for this article is http://msdn.microsoft.com/en-us/library/ms731060.aspx

Service Versioning

After initial deployment, and potentially several times during their lifetime, services (and the endpoints they expose) may need to be changed for a variety of reasons, such as changing business needs, information technology requirements, or to address other issues. Each change introduces a new version of the service. This topic explains how to consider versioning in Windows Communication Foundation (WCF).

Four Categories of Service Changes

The changes to services that may be required can be classified into four categories:

  • Contract changes: For example, an operation might be added, or a data element in a message might be added or changed.

  • Address changes: For example, a service moves to a different location where endpoints have new addresses.

  • Binding changes: For example, a security mechanism changes or its settings change.

  • Implementation changes: For example, when an internal method implementation changes.

Some of these changes are called "breaking" and others are "nonbreaking." A change is nonbreaking if all messages that would have been processed successfully in the previous version are processed successfully in the new version. Any change that does not meet that criterion is a breaking change. This topic describes mechanisms for making nonbreaking changes in contracts, addresses, and bindings.

Service Orientation and Versioning

One of the tenets of service orientation is that services and clients are autonomous (or independent). Among other things, this implies that service developers cannot assume that they control or even know about all service clients. This eliminates the option of rebuilding and redeploying all clients when a service changes versions. This topic assumes the service adheres to this tenet of service orientation and therefore must be changed or "versioned" independent of its clients.

In cases where a breaking change is unexpected and cannot be avoided, an application may choose to ignore this tenet and require that clients be rebuilt and redeployed with a new version of the service. That scenario does not receive further discussion here.

Contract Versioning

Contracts used by a client do not need to be the same as the contract used by the service; they need only to be compatible.

For service contracts, compatibility means new operations exposed by the service can be added but existing operations cannot be removed or changed semantically.

For data contracts, compatibility means new schema type definitions can be added but existing schema type definitions cannot be changed in breaking ways. Breaking changes might include removing data members or changing their data type incompatibly. This feature allows the service some latitude in changing the version of its contracts without breaking clients. The next two sections explain nonbreaking and breaking changes that can be made to WCF data and service contracts.

Data Contract Versioning

This section deals with data versioning when using the DataContractSerializer and DataContractAttribute classes.

Strict Versioning

In many scenarios when changing versions is an issue, the service developer does not have control over the clients and therefore cannot make assumptions about how they would react to changes in the message XML or schema. In these cases, you must guarantee that the new messages will validate against the old schema, for two reasons:

  • The old clients were developed with the assumption that the schema will not change. They may fail to process messages that they were never designed for.

  • The old clients may perform actual schema validation against the old schema before even attempting to process the messages.

The recommended approach in such scenarios is to treat existing data contracts as immutable and create new ones with unique XML qualified names. The service developer would then either add new methods to an existing service contract or create a new service contract with methods that use the new data contract.

It will often be the case that a service developer needs to write some business logic that should run within all versions of a data contract plus version-specific business code for each version of the data contract. The appendix at the end of this topic explains how interfaces can be used to satisfy this need.

Lax Versioning

In many other scenarios, the service developer can make the assumption that adding a new, optional member to the data contract will not break existing clients. This requires the service developer to investigate whether existing clients are not performing schema validation and that they ignore unknown data members. In these scenarios, it is possible to take advantage of data contract features for adding new members in a nonbreaking way. The service developer can make this assumption with confidence if the data contract features for versioning were already used for the first version of the service.

WCF, ASP.NET Web Services, and many other Web service stacks support lax versioning: that is, they do not throw exceptions for new unknown data members in received data.

It is easy to mistakenly believe that adding a new member will not break existing clients. If you are unsure that all clients can handle lax versioning, the recommendation is to use the strict versioning guidelines and treat data contracts as immutable.

For detailed guidelines for both lax and strict versioning of data contracts, see Best Practices: Data Contract Versioning.

Distinguishing Between Data Contract and .NET Types

A .NET class or structure can be projected as a data contract by applying the DataContractAttribute attribute to the class. The .NET type and its data contract projections are two distinct matters. It is possible to have multiple .NET types with the same data contract projection. This distinction is especially useful in allowing you to change the .NET type while maintaining the projected data contract, thereby maintaining compatibility with existing clients even in the strict sense of the word. There are two things you should always do to maintain this distinction between .NET type and data contract:

  • Specify a Name and Namespace. You should always specify the name and namespace of your data contract to prevent your .NET type’s name and namespace from being exposed in the contract. This way, if you decide later to change the .NET namespace or type name, your data contract remains the same.

  • Specify Name. You should always specify the name of your data members to prevent your .NET member name from being exposed in the contract. This way, if you decide later to change the .NET name of the member, your data contract remains the same.

Changing or Removing Members

Changing the name or data type of a member, or removing data members, is a breaking change even if lax versioning is allowed. If this is necessary, create a new data contract.

If service compatibility is of high importance, you might consider ignoring unused data members in your code and leave them in place. If you are splitting up a data member into multiple members, you might consider leaving the existing member in place as a property that can perform the required splitting and re-aggregation for down-level clients (clients that are not upgraded to the latest version).

Similarly, changes to the data contract’s name or namespace are breaking changes.

Round-Trips of Unknown Data

In some scenarios, there is a need to "round-trip" unknown data that comes from members added in a new version. For example, a "versionNew" service sends data with some newly added members to a "versionOld" client. The client ignores the newly added members when processing the message, but it resends that same data, including the newly added members, back to the versionNew service. The typical scenario for this is data updates where data is retrieved from the service, changed, and returned.

To enable round-tripping for a particular type, the type must implement the IExtensibleDataObject interface. The interface contains one property, ExtensionData that returns the ExtensionDataObject type. The property is used to store any data from future versions of the data contract that is unknown to the current version. This data is opaque to the client, but when the instance is serialized, the content of the ExtensionData property is written with the rest of the data contract members' data.

It is recommended that all your types implement this interface to accommodate new and unknown future members.

Data Contract Libraries

There may be libraries of data contracts where a contract is published to a central repository, and service and type implementers implement and expose data contracts from that repository. In that case, when you publish a data contract to the repository, you have no control over who creates types that implement it. Thus, you cannot modify the contract once it is published, rendering it effectively immutable.

When Using the XmlSerializer

The same versioning principles apply when using the XmlSerializer class. When strict versioning is required, treat data contracts as immutable and create new data contracts with unique, qualified names for the new versions. When you are sure that lax versioning can be used, you can add new serializable members in new versions but not change or remove existing members.

ms731060.note(en-us,VS.90).gifNote:
The XmlSerializer uses the XmlAnyElementAttribute and XmlAnyAttributeAttribute attributes to support round-tripping of unknown data.

Message Contract Versioning

The guidelines for message contract versioning are very similar to versioning data contracts. If strict versioning is required, you should not change your message body but instead create a new message contract with a unique qualified name. If you know that you can use lax versioning, you can add new message body parts but not change or remove existing ones. This guidance applies both to bare and wrapped message contracts.

Message headers can always be added, even if strict versioning is in use. The MustUnderstand flag may affect versioning. In general, the versioning model for headers in WCF is as described in the SOAP specification.

Service Contract Versioning

Similar to data contract versioning, service contract versioning also involves adding, changing, and removing operations.

Specifying Name, Namespace, and Action

By default, the name of a service contract is the name of the interface. Its default namespace is "http://tempuri.org", and each operation’s action is "http://tempuri.org/contractname/methodname". It is recommended that you explicitly specify a name and namespace for the service contract, and an action for each operation to avoid using "http://tempuri.org" and to prevent interface and method names from being exposed in the service’s contract.

Adding Parameters and Operations

Adding service operations exposed by the service is a nonbreaking change because existing clients need not be concerned about those new operations.

ms731060.note(en-us,VS.90).gifNote:
Adding operations to a duplex callback contract is a breaking change.

Changing Operation Parameter or Return Types

Changing parameter or return types generally is a breaking change unless the new type implements the same data contract implemented by the old type. To make such a change, add a new operation to the service contract or define a new service contract.

Removing Operations

Removing operations is also a breaking change. To make such a change, define a new service contract and expose it on a new endpoint.

Fault Contracts

The FaultContractAttribute attribute enables a service contract developer to specify information about faults that can be returned from the contract's operations.

The list of faults described in a service's contract is not considered exhaustive. At any time, an operation may return faults that are not described in its contract. Therefore changing the set of faults described in the contract is not considered breaking. For example, adding a new fault to the contract using the FaultContractAttribute or removing an existing fault from the contract.

Service Contract Libraries

Organizations may have libraries of contracts where a contract is published to a central repository and service implementers implement contracts from that repository. In this case, when you publish a service contract to the repository you have no control over who creates services that implement it. Therefore, you cannot modify the service contract once published, rendering it effectively immutable. WCF supports contract inheritance, which can be used to create a new contract that extends existing contracts. To use this feature, define a new service contract interface that inherits from the old service contract interface, then add methods to the new interface. You then change the service that implements the old contract to implement the new contract and change the "versionOld" endpoint definition to use the new contract. To "versionOld" clients, the endpoint will continue to appear as exposing the "versionOld" contract; to "versionNew" clients, the endpoint will appear to expose the "versionNew" contract.

Address and Binding Versioning

Changes to endpoint address and binding are breaking changes unless clients are capable of dynamically discovering the new endpoint address or binding. One mechanism for implementing this capability is by using a Universal Discovery Description and Integration (UDDI) registry and the UDDI Invocation Pattern where a client attempts to communicate with an endpoint and, upon failure, queries a well-known UDDI registry for the current endpoint metadata. The client then uses the address and binding from this metadata to communicate with the endpoint. If this communication succeeds, the client caches the address and binding information for future use.

Appendix

The general data contract versioning guidance when strict versioning is needed is to treat data contracts as immutable and create new ones when changes are required. A new class needs to be created for each new data contract, so a mechanism is needed to avoid having to take existing code that was written in terms of the old data contract class and rewrite it in terms of the new data contract class.

One such mechanism is to use interfaces to define the members of each data contract and write internal implementation code in terms of the interfaces rather than the data contract classes that implement the interfaces. The following code for version 1 of a service shows an IPurchaseOrderV1 interface and a PurchaseOrderV1:

public interface IPurchaseOrderV1
{
string OrderId { get; set; }
string CustomerId { get; set; }
}

[DataContract(
Name = "PurchaseOrder",
Namespace = "http://examples.microsoft.com/WCF/2005/10/PurchaseOrder")]
public class PurchaseOrderV1 : IPurchaseOrderV1
{
[DataMember(...)]
public string OrderId {...}
[DataMember(...)]
public string CustomerId {...}
}

While the service contract’s operations would be written in terms of PurchaseOrderV1, the actual business logic would be in terms of IPurchaseOrderV1. Then, in version 2, there would be a new IPurchaseOrderV2 interface and a new PurchaseOrderV2 class as shown in the following code:

public interface IPurchaseOrderV2
{
DateTime OrderDate { get; set; }
}
[DataContract(
Name = "PurchaseOrder ",
Namespace = "http://examples.microsoft.com/WCF/2006/02/PurchaseOrder")]
public class PurchaseOrderV2 : IPurchaseOrderV1, IPurchaseOrderV2
{
[DataMember(...)]
public DateTime OrderId {...}
[DataMember(...)]
public string CustomerId {...}
[DataMember(...)]
public DateTime OrderDate { ... }
}

The service contract would be updated to include new operations that are written in terms of PurchaseOrderV2. Existing business logic written in terms of IPurchaseOrderV1 would continue to work for PurchaseOrderV2 and new business logic that needs the OrderDate property would be written in terms of IPurchaseOrderV2.