Migrating ASP.NET Web Services to WCF

I am currently in the middle of a project where we are migrating a (large) amount of web services built on top of ASP.NET in .NET 2.0 (commonly referred to as ASMX Web Services) over to the Windows Communication Foundation (WCF) platform available in .NET 3.0. The primary reason we want to do that, is because we would like to take advantage of the binary message serialization support available in WCF to speed The Microsoft ASP.NET logo. up communication  between the services and their clients. This same technique was possible in earlier versions of the .NET Framework thanks to a technology called Remoting, which is now superceded by WCF. In both cases it requires that both the client and server run on .NET in order to work. But I digress.

Since the ASMX model has been for a long time the primary Microsoft technology for building web services on the .NET platform, I figured they must have laid out a nice migration path to bring all those web services to the new world of WCF. It turned out, they did!

The quick way

If you built your ASMX web services with code separation (that is, all programming logic resided in a separate code-behind file instead of being embedded in the ASMX file) it is possible to get an ASMX web service up and running in WCF pretty quickly by going through a few easy steps:

<% @ServiceHost Service="MyNamespace.MyService" %>
<system.serviceModel>
  <behaviors>
      <serviceBehaviors>
          <behavior name="MetadataEnabled">
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="true" />
          </behavior>
      </serviceBehaviors>
  </behaviors>
  <services>
      <service name="MyNamespace.MyService"
               behaviorConfiguration="MetadataEnabled">
          <endpoint name="HttpEndpoint"
                    address=""
                    binding="wsHttpBinding"
                    contract="MyNamespace.IMyService" />
          <endpoint name="HttpMetadata"
                    address="contract"
                    binding="mexHttpBinding"
                    contract="IMetadataExchange" />
          <host>
              <baseAddresses>
                  <add baseAddress="http://localhost/myservice" />
              </baseAddresses>
          </host>
      </service>
  </services>
</system.serviceModel>

Here is a summary of the changes you’ll have to make to your ASMX web service:

Where the change applies ASMX WCF
Web service class inheritance WebService -
Web service class attribute WebServiceAttribute ServiceContractAttribute
Web service method attribute WebMethodAttribute OperationContractAttribute
Data class attribute XmlRootAttribute DataContractAttribute
Data class field attribute XmlElementAttribute DataMemberAttribute
HTTP endpoint resource .ASMX .SVC

As a side note, if you are using .NET 3.5 SP1 the porting process gets a little easier, since WCF will automatically serialize any object that is part of a service interface without the need of any special metadata attached to it. This means you no longer have to decorate the classes and members exposed by a WCF service contract with the DataContract and DataMember attributes.

Important considerations

The simple process I just described works well for relatively simple web services, but in any real-world scenario you will have to take into consideration a few number of aspects:

So what if your ASMX web services are making extensive use of the ASP.NET session store or employ the ASP.NET security model? Is it a show-stopper? Luckily enough, no. There is a solution to keep all that ASP.NET goodness working in WCF. It is called ASP.NET Compatibility Mode.

Backwards compatibility

Running WCF services with the ASP.NET Compatibility Mode enabled will integrate them in the ASP.NET HTTP Pipeline, which of course means all ASP.NET infrastructure will be back in place and available from WCF at runtime. You can enable this mighty mode from WCF by following these steps:

[AspNetCompatibilityRequirements(
    RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class MyService : IMyService
{
    // Service implementation
}
<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>

Remember that this will effectively tie the WCF runtime to the HTTP protocol, just like with ASMX web services, which means it becomes prohibited to add any non-HTTP endpoints for your WCF services.

Good luck and please, let me know your feedback!

/Enrico

Enrico Campidoglio

Enrico Campidoglio

Freelance programmer, trainer and mentor helping teams develop software better. I write this blog because I love sharing stories about the things I know. More about me →

Get in touch

Want me to speak at your company or event? Interested in hiring me? I'd love to hear from you.