Modifying a Service Contract


A service contract is an interface that the WCF tools and infrastructure can convert into a WSDL document, listing the operations for a service as a series of SOAP messages and message responses. You provide an implementation of these methods in a class in the service. When a service executes, the WCF runtime creates a channel stack by using the bindings specified in the service configuration file and listens for client requests in the form of one of these messages. The WCF runtime then converts each SOAP message sent by a client application into a method call and invokes the corresponding method in an instance of the class implementing the service (you will learn how and when the WCF runtime actually creates this instance in Chapter 7, “Maintaining State and Sequencing Operations”). Any data returned by the method is converted back into a SOAP response message and is sent back through the channel stack for transmission to the client application.

You can draw two conclusions from the preceding discussion:

  1. The service contract does not depend on the communication mechanism that the service uses to send and receive messages. The communications mechanism is governed by the channel stack constructed from the binding information specified in the service configuration file. You can change the network protocol or address of a service without modifying the code in the service or in any client applications that access the service (although client applications must use compatible endpoints in their configuration files). To a large extent, the security requirements of a service are also independent of the service contract, although there are exceptions, as you will see in this chapter.

  2. Client applications wishing to communicate with the service must be able to construct the appropriate SOAP messages. These messages depend on the service contract; if the service contract changes, then the client must be provided with an up-to-date version, otherwise, it runs the risk of sending messages that the service does not understand or that are formatted incorrectly. Alternatively, if the response messages returned by a service change, a client application might not be able to handle them correctly.

You will examine what this means from a practical perspective in the exercises in this section.

Selectively Protecting Operations

The previous two chapters have shown how to protect the messages passing between client applications and services. However, the techniques shown have concentrated on using bindings and behaviors of a service to protect the service as a whole. By modifying the service contract, you can specify different security requirements for operations in the same service.

Note 

Protecting a service by modifying binding and behavior information is an example of the fourth tenet of SOA–compatibility is based on policy. You can protect a service in a variety of ways without modifying the service contract, as long as the client applications and service follow compatible security policies. Selectively protecting an operation is a change to the service contract because now the protection mechanism becomes tightly coupled to the operation, rather than being a policy attribute of the service.

Specify the security requirements for operations in the WCF service

  1. Using Visual Studio 2005, open the solution file image from book ProductsService.sln located in the Microsoft Press\WCF Step By Step\Chapter 6\ProductsService folder under your \My Documents folder.

    This solution contains an amended copy of the ProductsClient, ProductsService, and ProductsServiceHost projects from Chapter 4, “Protecting an Enterprise WCF Service” (the service does not display a message box showing the identity of the user, and the client application contains an additional exception handler).

  2. Edit the image from book ProductsService.cs file in the ProductsService project, and locate the IProductsService interface that defines the service contract.

  3. In the IProductsService interface, amend the OperationContract attribute for the ListProducts and GetProduct methods as shown in bold below:

     [ServiceContract] public interface IProductsService {     // Get the product number of every product     …     [OperationContract(ProtectionLevel =                        System.Net.Security.ProtectionLevel.EncryptAndSign)]     List<string> ListProducts();     // Get the details of a single product     [OperationContract(ProtectionLevel =                        System.Net.Security.ProtectionLevel.EncryptAndSign)]     Product GetProduct(string productNumber);      }

    The ProtectionLevel property of the OperationContract attribute specifies how messages invoking this operation, and output by this operation, are protected. In this case, calls to the ListProducts and GetProduct operations must be signed by the client and encrypted by using a key negotiated with the service. This requires that the security mode of the binding used by the client and service specified message level authentication and that the client and service specify the same value for the AlgorithmSuite property (go back and look at Chapter 4 if you need to refresh your memory about these properties). In fact, this is the default protection level for operations when you configure message level security.

  4. Modify the OperationContract attribute for the CurrentStockLevel and ChangeStockLevel methods as shown in bold below:

     [ServiceContract] public interface IProductsService {     …     // Get the current stock level for a product     [OperationContract(ProtectionLevel =                        System.Net.Security.ProtectionLevel.Sign)]     int CurrentStockLevel(string productNumber);     // Change the stock level for a product     [OperationContract(ProtectionLevel =                        System.Net.Security.ProtectionLevel.Sign)]     bool ChangeStockLevel(string productNumber, int newStockLevel,                           string shelf, int bin); }

    Calls to theses operations must be signed, but not encrypted. The protection level specified here overrides the message level security configured for the binding. You can also specify a value of System.Net.Security.ProtectionLevel.Sign if you don’t want to sign messages either, although you should use this setting with caution as it has obvious security implications.

  5. Edit the image from book app.config file in the ProductsClient project by using the WCF Service Configuration Editor.

  6. In the WCF Service Configuration Editor, expand the Bindings folder and then select the ProductsClientTcpBindingConfig binding configuration. In the right pane, click the Security tab. Verify that the Mode property is set to Message, the AlgorithmSuite property is set to Basic128, and the MessageClientCredentialType property is set to Windows.

    Note 

    For simplicity, these exercises assume that the client application and WCF service operate in the same Windows domain. If you are running in an Internet environment, you can change the MessageClientCredentialType to UserName or Certificate, as described in Chapter 5, “Protecting a WCF Service over the Internet.”

  7. Save any changes you have made to the image from book app.config file, and then close the WCF Service Configuration Editor.

  8. Edit the image from book App.config file in the ProductsServiceHost project by using the WCF Service Configuration Editor. Follow the procedure in Step 6 to verify that the security settings for the ProductsServiceTcpBindingConfig binding configuration match those of the client application.

  9. In the left pane, expand the Diagnostics folder and then click the Message Logging node. In the right pane, set the LogMessagesAtServiceLevel property to False but ensure that the LogMessagesAtTransportLevel property is set to True.

    You will use the Service Trace Viewer to examine the messages sent between the client application and the service. To minimize the logging overhead, the WCF runtime will only trace messages as they flow in and out of the transport level. At this level, you will be able to see the effects of the message level security applied by the binding and the service contract–logging at the service (message) level will only show unencrypted messages as they are received and sent by the service.

  10. In the left pane, expand the Listeners folder, and then click the MessageLog node. Set the InitData property to the Products.svclog file in the Microsoft Press\WCF Step By Step\Chapter 6 folder under your \My Documents folder.

  11. Save the changes, and exit the Service Configuration Editor.

Test the modified service

  1. Start the solution without debugging. In the ProductsServiceHost form, click Start (if a Windows Security Alert message box appears, click Unblock to allow the service to open the TCP port it uses for listening for client requests). In the client console window, press Enter.

    Tests 1 and 2 complete successfully because the binding implements a policy of encryption and signing, and this automatically meets the requirements of the operation contract for the ListProducts and GetProduct operations. However, test 3 raises the exception, “The primary signature must be encrypted” because the CurrentStockLevel operation specifies only signing in the operation contract, but the binding is also encrypting information. The problem is that you have modified the service contract, but you have not updated the corresponding code in the client application; the proxy used by the client application is still expecting to send signed and encrypted messages to the service for tests 3 and 4.

  2. Press Enter to close the client console window. In the ProductsServiceHost form, click Stop and then close the form.

  3. In Visual Studio 2005, open the image from book Products.cs file in the ProductsClient project.

    This file contains the code for the proxy that you generated by using the svcutil tool in Chapter 3, “Making Applications and Services Robust.” You now have two choices: you can regenerate the proxy again or you can modify the code in this file to incorporate the changes required. Under normal circumstances, it would be advisable to regenerate the proxy, but in this case it is more informative for you to modify the code so that you can see the changes required in the proxy code.

  4. Scroll through the image from book Products.cs file to locate the definition of the IProductsService interface (this should be somewhere around line 228).

    You should be able to recognize the methods in this interface as they correspond very closely to the methods in the service contract. The return type of the ListProducts method is slightly different–it is an array of strings rather than a generic list, and the OperationContract and FaultContract attributes for each operation include Action and ReplyAction properties identifying the names of the SOAP messages that the WCF runtime uses when communicating with the WCF service.

  5. Modify the OperationContract attribute for the CurrentStockLevel and ChangeStockLevel methods as shown in bold below (do not modify the Action and ReplyAction properties):

     [System.ServiceModel.OperationContractAttribute(ProtectionLevel=System.Net.Security. ProtectionLevel.Sign, Action= )] int CurrentStockLevel(string productNumber); [System.ServiceModel.OperationContractAttribute(ProtectionLevel = System.Net.Security. ProtectionLevel.Sign, Action = )] bool ChangeStockLevel(string productNumber, int newStockLevel, string shelf, int bin);

  6. Using Windows Explorer, delete the Products.svclog file in the Microsoft Press\WCF Step By Step\Chapter 6 folder under your \My Documents folder.

  7. In Visual Studio 2005, start the solution without debugging. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

    All tests should now complete successfully.

  8. Press Enter to close the client console window. In the ProductsServiceHost form, click Stop and then close the form.

  9. Start the Service Trace Viewer (in the Microsoft Windows SDK, Tools program group).

  10. In the Service Trace Viewer, open the Products.svclog file in the Microsoft Press\WCF Step By Step\Chapter 6 folder under your \My Documents folder.

  11. In the left pane, click the Message tab. You should see six messages concerned with negotiating the encryption keys used by the client and service; these messages have an Action in the http://schemas.xmlsoap.org namespace. Following these are ten messages corresponding to the messages received by the service, and the responses sent back to the client application with an Action in the http://tempuri.org namespace. There are two further messages at the end, again with an Action in the http://schemas.xmlsoap.org namespace.

    Tip 

    Expand the Action column in the left pane to see more of the name for each action.

  12. Click the message with the Action http://tempuri.org/IProductsService/ListProducts. In the lower right pane, click the Formatted tab and scroll to the bottom of the pane to display the Envelope Information section (if the Envelope Section is not visible, expand the Message Log area in this pane). In the Parameters box, note that the Method used to send the data is e:EncryptedData, and that the parameter sent by the client application has been encrypted, as highlighted in the following image:

    image from book

  13. In the left pane, click the message with the Action http://tempuri.org/IProductsService/ListProductsResponse. In the lower-right pane, verify that this response message is also encrypted. Follow the same procedure to examine the http://tempuri.org/IProductsService/GetProduct and http://tempuri.org/IProductsService/GetProductResponse messages and verify that they are also encrypted.

  14. In the left pane, click the http://tempuri.org/IProductsService/ChangeStockLevel message. In the lower right pane, you should observe that the Method is CurrentStockLevel and that the parameter is an unencrypted product number:

    image from book

  15. In the left pane, click the http://tempuri.org/IProductsService/ChangeStockLevelResponse message. This message should also be unencrypted. Examine the http://tempuri.org/IProductsService/ChangeStockLevel and http://tempuri.org/IProductsService/ChangeStockLevelResponse messages. These messages should be unencrypted as well.

  16. In the File menu, click Close All. Leave the Service Trace Viewer open.

Versioning a Service

Change happens. It is almost inevitable that a widely used service will evolve as circumstances and business process change. In many cases, these changes will manifest themselves as modifications to the code that implements the operations in a service. However, it is also possible that the definitions of operations might need to change as well; you might need to add new operations, retire old or redundant operations, or change the parameters and return types of existing operations. Clearly, these modifications require updating the service contract. However, client applications depend on the service contract to specify the messages that the service receives and the responses it sends. If the service contract changes, what happens to clients that used the previous version of the contract? Will they still work or do you need to go and visit every client installation and update the code? Do you actually know where to locate every client? If client applications connect across the Internet, there could be a large number of them located anywhere in the world.

You can see that modifying a service is not a task that you should undertake lightly and, as far as possible, you should take steps to ensure that existing clients will continue to function without requiring to be updated. To this end, it helps to understand what actually happens when you change a service or a service contract and the strategies that you can follow to minimize any detrimental impact of these changes. The following exercises illustrate some common scenarios.

Add a method to the WCF service and amend the business logic of operations

  1. Using Visual Studio 2005, edit the image from book ProductsService.cs file in the ProductsService project.

  2. Add the following method to the ProductsServiceImpl class:

     public bool IsPotentialSqlInjectionAttack(string data) {     // Check to see whether the data contains a rogue character     // or the string "--", or the string "/*"     char[] rogueChars = { ';', '\'', '\\', '"', '=', '%', '_', '*' };     if ((data.IndexOfAny(rogueChars) != -1) ||          data.Contains("--") || data.Contains("/*"))         return true;     else         return false; }

    Note 

    A copy of this code is supplied in the PotentialSqlInjectionAttack.txt file, in the Microsoft Press\WCF Step By Step\Chapter 6 folder under your \My Documents folder.

    The Adventure-Works organization has recently conducted a security audit of some of their applications. The auditors have identified the ProductsService service as being prone to a SQL injection attack. This method checks a string for characters and substrings that are typically used by an attacker, returning true if the string is suspect and false if the string seems safe.

    More Info 

    For a description of what a SQL injection attack is and how dangerous it can be, see the SQL Injection topic in SQL Server Books Online, also available at http://msdn2.microsoft.com/en-us/library/ms161953.aspx. The solution shown here is quite primitive, but gives you an idea of what you need to do to protect your service. Alternative strategies exist, such as using SQL parameters, to provide the data values to the SQL statement.

  3. Add the statements shown below in bold to the start of the GetProduct method, before the code that connects to the database:

     public Product GetProduct(string productNumber) {     // Check for potential SQL Injection attack     if (IsPotentialSqlInjectionAttack(productNumber))     {         return new Product();     }     // Connect to the AdventureWorks database      }

    If the productNumber provided by the user contains characters that are commonly used by a SQL Injection attack, the method simply returns an empty product, otherwise, it operates as before.

    Important 

    Do not return an error message in this situation. An attacker could use this information to determine that you are explicitly checking for SQL injection attacks and attempt to probe further. Returning a value that contains no meaningful data provides no further information to the attacker. Additionally, although not shown in this example, you should also log this message, and record the identity of the user sending the message.

  4. Add the following statements to the start of the CurrentStockLevel method:

     public int CurrentStockLevel(string productNumber) {     // Check for potential SQL Injection attack     if (IsPotentialSqlInjectionAttack(productNumber))     {         return 0;     }     // Connect to the AdventureWorks database      }

    If the user provides a suspect product number, the method returns a stock level of zero.

  5. Add the statements shown below to the start of the ChangeStockLevel method:

     public bool ChangeStockLevel(string productNumber, int newStockLevel,                              string shelf, int bin) {     // Check for potential SQL Injection attack     if (IsPotentialSqlInjectionAttack(productNumber) ||         IsPotentialSqlInjectionAttack(shelf))     {         return false;     }      }

    This time you need to check two string parameters. The method returns false and does not update the database if either string is suspicious.

  6. Start the solution without debugging. In the ProductsServiceHost form, click Start In the client console window, press Enter.

    All tests should execute successfully.

  7. Press Enter to close the client console window. In the ProductsServiceHost form, click Stop and then close the form.

  8. In Visual Studio 2005, edit the image from book Program.cs file in the ProductsClient project. In the Main method, locate the statement that invokes the GetProduct operation and change the parameter that the client sends to this operation, like this:

     Product product =     proxy.GetProduct("WB-H098'; DELETE FROM Production.Product --");

    This rather sneaky piece of code passes a string that contains a valid product number but also contains an SQL DELETE statement that maliciously attempts to delete all products from the AdventureWorks database. Although this would most likely fail (even without the code that checks for an SQL injection attack) because of the referential integrity checking performed by SQL Server, it is still a loophole you would probably rather not leave exposed.

  9. Start the solution without debugging. In the ProductsServiceHost form, click Start In the client console window, press Enter.

    Tests 1, 2, and 4 perform successfully, but the output from test 2 displays an “empty” product–all the fields are either blank or zero:

    image from book

  10. Press Enter to close the client console window. In the ProductsServiceHost form, click Stop and then close the form.

  11. Edit the image from book Program.cs file in the ProductsClient project, and change the line that calls the GetProduct method back to its original state:

     Product product = proxy.GetProduct("WB-H098");

Although the service has changed and a new public method has been added, the service contract has not been updated. The IsPotentialSqlInjectionAttack method is not accessible to client applications, which can continue to access the service exactly as before. This is an example of a nonbreaking change to a service.

Add a parameter to an existing operation in the service contract

  1. Using Visual Studio 2005, edit the image from book ProductsService.cs file in the ProductsService project.

  2. Locate the definition of the IProductsService interface. Add a parameter to the ListProducts method, as follows:

     List<string> ListProducts(string match)

    The Adventure-Works organization has dramatically increased the number of products that they manufacture. The original ListProducts method returns a list comprising thousands of rows. It has therefore been decided to modify this operation to enable the user to constrain the list of products returned to be those whose name matches a string specified by the user.

  3. In the ProductsServiceImpl class, update the definition of the ListProducts method:

     public List<string> ListProducts(string match)

  4. Add the following statements to the start of the method, before the code that reads the configuration information for connecting to the database:

     // Check for potential SQL Injection attack if (IsPotentialSqlInjectionAttack(match)) {     return new List<string>(); }

  5. Change the SQL statement that retrieves the product numbers from the database as shown in bold below:

     // Retrieve the details of all products by using a DataReader IDataReader productsReader; try {     string queryString = @"SELECT ProductNumber                            FROM Production.Product                            WHERE Name LIKE '%" + match + "%'";     productsReader = dbAdventureWorks.ExecuteReader(CommandType.Text, queryString); }

  6. Start the solution without debugging. In the ProductsServiceHost form, click Start In the client console window, press Enter

    Test 1 fails, reporting an internal error:

    image from book

  7. Press Enter to close the client console window. In the ProductsServiceHost form, click Stop and then close the form.

The problem now is that the client application is attempting to invoke a version of an operation that the service no longer implements (the SOAP message expected by the service includes a parameter that the client has not supplied). This is a breaking change, and presents an issue that you must address. You will see how in the following exercises.

Add a new operation to the WCF service

  1. Using Visual Studio 2005, edit the image from book ProductsService.cs file in the ProductsService project.

  2. In the IProductsService interface, remove the parameter from the ListProducts method and add another version of the ListProducts method, called ListSelectedProducts, that includes this parameter to the interface, as follows:

     // Get the product number of every product [FaultContract(typeof(ConfigFault))] [FaultContract(typeof(DatabaseFault))] [OperationContract(ProtectionLevel=                    System.Net.Security.ProtectionLevel.EncryptAndSign)] List<string> ListProducts();  // Get the product number of selected products [FaultContract(typeof(ConfigFault))] [FaultContract(typeof(DatabaseFault))] [OperationContract(ProtectionLevel =                    System.Net.Security.ProtectionLevel.EncryptAndSign)] List<string> ListSelectedProducts(string match); 

    Note 

    C# permits you to have multiple methods in an interface and a class that have the same name as long as their signatures differ. This is called “overloading.” So, in theory, you could create two versions of the same method, both called ListProducts, one which takes no parameters and the other which takes a single string parameter. However, the SOAP standard does not allow a service to expose multiple operations that share the same name in the same service, so this approach would fail.

    Apart from giving the operations different names in the C# interface, an alternative approach is to use the Name property of the OperationContract attribute in the service contract, like this:

     [OperationContract(Name="ListSelectedProducts", …] List<string> ListProducts(string match);

    WCF uses this property to generate the names for the SOAP request and response messages. If you don’t provide a value for the Name property, WCF uses the name of the method instead. You should also notice that the name of an operation in a service contract impacts the SOAP request and response messages, and changing the name of an operation is therefore a breaking change to the service contract.

  3. In the ProductsServiceImpl class, change the name of the ListProducts method to ListSelectedProducts:

     [PrincipalPermission(SecurityAction.Demand, Role = "WarehouseStaff")] public List<string> ListSelectedProducts(string match) {      }

  4. Add a new implementation of the original ListProducts method to the ProductsServiceImple class, like this:

     [PrincipalPermission(SecurityAction.Demand, Role = "WarehouseStaff")] public List<string> ListProducts() {     return ListSelectedProducts(""); }

    The ListProducts method uses the ListSelectedProducts method, passing in an empty string as the parameter. The SQL SELECT statement in the ListSelectedProducts method will therefore return all products; the query criteria it generates will be “WHERE Name LIKE ‘%%’.”

  5. Start the solution without debugging. In the ProductsServiceHost form, click Start In the client console window, press Enter. All tests should now succeed.

  6. Press Enter to close the client console window. In the ProductsServiceHost form, click Stop and then close the form.

Adding a new operation to a service contract is another nonbreaking change. New client applications can send messages corresponding to the new operation (you can generate a proxy that includes the new operation by using the svcutil utility if you are building a WCF client application). Existing client applications using the old version of the proxy still continue to function, but are not aware that the new operation exists.

There is still a potential issue, however. If you want new client applications to be able to call only the new operation (ListSelectedProducts) and not use the older operation (ListProducts), how can you hide this operation from them? The answer is to use multiple service contracts. Keep the existing service contract unchanged, and define a new service contract that includes the new version of the operation, but not the old version. The code fragments below show the existing contract (IProductsService), and the new one (IProductsServiceV2). The code fragments also show the recommended way of identifying and naming the different versions of a service contract by using the Namespace and Name properties of the ServiceContract attribute. By default, the service contract uses the namespace “http://tempuri.org,” and takes its name from the name of the interface (if you recall, when using the Service Trace Viewer to examine the messages sent to the ProductsService, you saw that they were all of the form “http://tempuri.org/IProductsService/”). When defining a new version of a service contract, use the Namespace property to identify the version by including the date, but keep the Name property the same for each version. However, be warned that modifying the Namespace or Name properties of a service contract constitutes a breaking change as these items are used to help identify the SOAP messages sent between the client application and the service:

 // Service contract describing the operations provided by the WCF service [ServiceContract(Namespace="http://adventure-works.com/2006/07/04",                  Name="ProductsService")] public interface IProductsService {     // Get the product number of every product     [FaultContract(typeof(ConfigFault))]     [FaultContract(typeof(DatabaseFault))]     [OperationContract(ProtectionLevel=                        System.Net.Security.ProtectionLevel.EncryptAndSign)]     List<string> ListProducts();     // Get the details of a single product     … } // Version 2 of the service contract [ServiceContract(Namespace="http://adventure-works.com/2006/08/31",                  Name="ProductsService")] public interface IProductsServiceV2 {     // Get the product number of selected products     [FaultContract(typeof(ConfigFault))]     [FaultContract(typeof(DatabaseFault))]     [OperationContract(ProtectionLevel =                        System.Net.Security.ProtectionLevel.EncryptAndSign)]     List<string> ListSelectedProducts(string match);     // Get the details of a single product      }

The service implementation class, ProductsServiceImpl, should implement both of these interfaces. The code for the methods common to both interfaces (GetProduct, CurrentStockLevel, and ChangeStockLevel) needs to be provided only once in this class:

 public class ProductsServiceImpl : IProductsService, IProductsServiceV2 {     // Implement ListProducts, ListSelectedProducts,     // GetProduct, CurrentStockLevel, and ChangeStockLevel     … }

Finally, create a separate set of endpoints for the new version of the service contract (one for each binding). You can use the WCF Service Configuration Editor, or edit the service configuration file by hand, to add an endpoint with the contract attribute set to Products.IProductsServiceV2:

 <system.serviceModel>     ...     <services>         <service behaviorConfiguration="…"                name="Products.ProductsServiceImpl">         …             <endpoint binding="…" bindingConfiguration="…"                    name="…" contract="Products.IProductsServiceV2" />         </service>     </services> </system.serviceModel>

Note 

You can find a working implementation of the ProductsService service, and a client application, that provides these two versions of the service contract in the ProductsServiceV2 folder, located in the Microsoft Press\WCF Step By Step\Chapter 6 folder under My Documents. You will make use of this solution later in this chapter.

Making Breaking and Nonbreaking Changes to a Service Contract

Strictly speaking, you should consider a service contract to be immutable; any changes that you make to the contract are likely to affect client applications, which might no longer be able to communicate with the service correctly. In practice, you have seen that you can make some changes to a service contract without breaking the terms of this contract as far as a WCF client application is concerned. Table 6-1 summarizes some common changes that developers frequently make to service contracts and the effects that these changes can have on existing client applications.

Table 6-1: Service Contract Changes
Open table as spreadsheet

Change

Effect

Adding a new operation

This is a nonbreaking change. Existing client applications are unaffected, but the new operation is not visible to WCF client applications connecting to the service by using a proxy generated from the WSDL description of the original service contract. Existing client applications that dynamically query services and construct messages can use the new operation. For more details, see Chapter 10, “Programmatically Controlling the Configuration and Communications.”

Removing an operation

This is a breaking change. Existing client applications that invoke the operation will no longer function correctly, although client applications that do not use the operation remain unaffected.

Changing the name of an operation

This is a breaking change. Existing client applications that invoke the operation will no longer work, although client applications that do not use the operation remain unaffected.

Note that the name of an operation defaults to the name of the method in the service contract. You can change the name of a method but retain the original name of the operation by using the Name property in the OperationContract attribute of the method, like this:

[OperationContract (Name="ListProducts")]

List<string> ListAllProducts();

This is good practice, as it removes any dependency between the service contract and the name of the physical method that implements the operation.

Changing the protection level of an operation

This is a breaking change. Existing client applications will not be able to invoke the operation.

Adding a parameter to an operation

This is a breaking change. Existing client applications will no longer be able to invoke the operation, as the SOAP messages they send will be incompatible with the SOAP messages expected by the service.

Reordering parameters in an operation

This is a breaking change. The results are not easily predictable (some existing client applications might continue to work).

Removing a parameter from an operation

This is a breaking change. As with reordering parameters, the results are not easily predictable.

Changing the types of parameters or the return type of an operation

This is a breaking change. Existing client applications might continue to function, but there is a significant risk that data in SOAP messages will be lost or misinterpreted. This includes applying or removing the ref and out modifiers to parameters, even if the underlying type does not change. For more information, see the section “Modifying a Data Contract” later in this chapter.

Adding a FaultContract to an operation

This is a breaking change. Existing client applications can be sent fault messages that they will not be able to interpret correctly.

Removing a FaultContract from an operation

This is a nonbreaking change. Existing client applications will continue to function correctly, although any handlers for trapping the faults specified by this fault contract will be rendered obsolete.

Changing the Name or Namespace property of the ServiceContract attribute for a service contract

This is a breaking change. Existing client applications that use the previous name or namespace will no longer be able to send messages to the service.

Making breaking changes to a service contract requires you to update the client applications that use the service. If client applications use WCF proxies, you will need to regenerate these proxies. However, the recommended approach for modifying a service contract is to create a new version and to leave the existing version intact, as described in the previous section. This removes the requirement for you to update existing client applications, although they will not be able to use any new features of the service.




Microsoft Windows Communication Foundation Step by Step
Microsoft Windows Communication Foundation Step by Step (Step By Step Developer Series)
ISBN: 0735623368
EAN: 2147483647
Year: 2007
Pages: 105
Authors: John Sharp

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net