Migrating a Versionable ASMX Web Service to WCF
December 21, 2008Creating a versionable ASMX Web Service is something that was really hard to do in .NET 1.1, mostly because it involved a lot of work and discipline. Creating versionable services has become quite easy with WCF because this is an out-of-the-box feature. But what about those web services you already created and that are being used by possibly dozens of applications? Are you stuck with those pesky ASMX Web services or is it possible to easily move them to WCF without much effort? As it turns out, you can replace your old ASMX web services with WCF even without the need to change or recompile the client software applications.
First, let’s talk about how I’ve been developing versionable ASMX web services in the past. After that, I’ll show you how to easily migrate an ASMX web service to WCF.
Versionable ASMX Web Services in .NET 1.1
For building versionable ASMX web services, I’ve been using XML messages with a version number that indicates the particular edition of a message. These XML messages are composed by a service agent component. This service agent component is responsible for providing a strongly type interface to the using applications and mapping these to their respective XML representation. The service agent then makes a call to the ASMX web service after which it translates/validates the received XML response back to a strongly typed representation.
When the ASMX web service receives a message from a service agent, it first extracts the version number and then sends it to an appropriate message handler for that particular version. The message is then translated back to an object representation after which the requested action is executed.
I agree that this is a lot of work, but it turned out very well in a .NET 1.1 environment. It adds the tremendous benefit of being able to change the contract (= new version) of the ASMX web service without the need to change any of the client applications. Regression tests are certainly desirable before releasing a new version in order to check whether the most recent changes didn’t break anything for the older contracts.
This simple code sample illustrates how a service agent might work:
public class ServiceAgent
{
private readonly ServiceCredentials _serviceCredentials;
public ServiceAgent(ServiceCredentials serviceCredentials)
{
_serviceCredentials = serviceCredentials;
}
public ProcessingResult ProcessOrder(Order order)
{
OrderXmlRequestMapper xmlRequestMapper =
new OrderXmlRequestMapper();
String xmlRequest = xmlRequestMapper.MapFrom(order);
String xmlResponse = String.Empty;
using(AsmxService service = ServiceProxyFactory.
CreateServiceProxy(typeof(AsmxService),
_serviceCredentials))
{
xmlResponse = service.ProcessOrder(xmlRequest);
}
ProcessingResultXmlResponseMapper xmlResponseMapper =
new ProcessingResultXmlResponseMapper();
ProcessingResult result =
xmlResponseMapper.MapFrom(xmlResponse);
return result;
}
}
And this is some sample code for an ASMX web service:
[WebService(Namespace = http://www.jvr.be/AsmxService)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class AsmxService : WebService
{
[WebMethod(MessageName = "ProcessOrder")]
public String ProcessOrder(String xmlRequest)
{
// Convert the XML request back to objects
// Process the order
Debug.Write("ProcessOrder on ASMX service called.");
// Return an XML response
String xmlResponse = "This is a versioned reponse.";
return xmlResponse;
}
}
Notice how dutifully a meaningful namespace for the web service and a message name for the web method is provided. This is something that I always considered a best practice. Turns out that it does have some benefits.
Anyway, enough is enough. Let’s see how we can replace such an ASMX web service with a WCF service.
Migrating from ASMX web services to WCF
When migrating to a WCF service, we obviously want the existing client applications to keep working with the service agents. New applications can use a WCF client proxy for communicating with a new contract of the WCF service. This way we can use the versioning technology of WCF for future releases. Existing applications can gradually move to a WCF client proxy as well, but at their own pace.
The whole setup is to trick the service agents that the ASMX web service is still there while it actually is replaced with a WCF service that provides an extra service contract that mimics the old ASMX web service for backwards compatibility. Let’s see how we can do this in code.
First we define a service contract for the old ASMX web service.
[ServiceContract(Namespace = http://www.jvr.be/AsmxService)]
public interface IOldAsmxService
{
[OperationContract(
Action = http://www.jvr.be/AsmxService/ProcessOrder)]
String ProcessOrder(String xmlRequest);
}
Notice the namespace provided by the ServiceContract and the action for the OperationContract. This is how the new service contract looks like:
[ServiceContract]
public interface IWcfService
{
[OperationContract]
ProcessOrderResponse ProcessOrder(
ProcessOrderRequest request);
}
Implementing the concrete service class is somewhat straightforward:
[ServiceBehavior(Namespace = http://www.jvr.be/AsmxService)]
public class WcfService : IWcfService, IOldAsmxService
{
public ProcessOrderResponse ProcessOrder(
ProcessOrderRequest request)
{
// Process the order
Debug.Write("ProcessOrder of IWcfService called.");
return new ProcessOrderResponse();
}
public String ProcessOrder(String xmlRequest)
{
// Map XML request to a ProcessOrderRequest
// (in a separate mapper class!!)
// Process the order
Debug.Write("ProcessOrder of IOldAsmxService called.");
var response = ProcessOrder(new ProcessOrderRequest());
// Map ProcessOrderResponse to a XML response
// (in a separate mapper class!!)
return "Some mapped XML reponse";
}
}
Notice that the service method that supports the contract of the old ASMX web service delegates its call to to the new method. You can also do this the other way around if you want.
The first step to make this all work is to add a new file with an .asmx extension that contains the following line:
<%@ ServiceHost language=c# Debug=”true” Service=”Jvr.WcfService” %%>
The next step is to add the following configuration settings to the web.config file of the WCF service.
<system.web>
<compilation debug="false">
<buildProviders>
<remove extension=".asmx"/>
<add extension=".asmx"
type="System.ServiceModel.Activation.ServiceBuildProvider,
System.ServiceModel, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
</buildProviders>
</compilation>
</system.web>
Make sure to create an endpoint for both the old and the new service contracts. You have to use basicHttpBinding for the old service contract. Now you can replace your old ASMX service with a new shiny WCF service and this without breaking any client applications.
Thoughts? Flames? Anything? Please let me know.
If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at info. @ principal-it .be
Jan Van Ryswyck
Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.
Comments
Writing Maintainable
Unit Tests
Watch The Videos
Latest articles
-
Contract Tests - Parameterised Test Cases
June 28, 2023
-
Contract Tests - Abstract Test Cases
April 12, 2023
-
Contract Tests
February 1, 2023
-
The Testing Quadrant
June 15, 2022
-
Tales Of TDD: The Big Refactoring
February 2, 2022
Tags
- .NET
- ALT.NET
- ASP.NET
- Agile
- Announcement
- Architecture
- Behavior-Driven Development
- C++
- CQRS
- Clojure
- CoffeeScript
- Community
- Concurrent Programming
- Conferences
- Continuous Integration
- Core Skills
- CouchDB
- Database
- Design Patterns
- Domain-Driven Design
- Event Sourcing
- F#
- Fluent Interfaces
- Functional Programming
- Hacking
- Humor
- Java
- JavaScript
- Linux
- Microsoft
- NHibernate
- NoSQL
- Node.js
- Object-Relational Mapping
- Open Source
- Reading
- Ruby
- Software Design
- SourceControl
- Test-Driven Development
- Testing
- Tools
- Visual Studio
- Web
- Windows
Disclaimer
The opinions expressed on this blog are my own personal opinions. These do NOT represent anyone else’s view on the world in any way whatsoever.
About
Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.
Latest articles
Contract Tests - Parameterised Test Cases
Contract Tests - Abstract Test Cases
Contract Tests
The Testing Quadrant
Contact information
(+32) 496 38 00 82
info @ principal-it .be