Phased Migration From ASMX to WCF

This question came up on an internal list recently (rephrasing the question slightly):

I have an ASMX service that is already exposed and is being consumed by a variety of user agents (mobile devices, windows forms, Java clients, etc). I want to change the service to use WCF without affecting existing clients. Is this possible?

Turns out there is a pretty cool way to handle this. Remember Kenny's double-decorator post? You can take your existing ASMX and overlay WCF attributes on the WebServiceAttribute decorated class and the WebMethodAttribute decorated operations. Your code-behind looks like this:

using System;

using System.Web;

using System.Collections;

using System.Web.Services;

using System.Web.Services.Protocols;

   

using System.ServiceModel;

   

[WebService(Namespace = "https://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[ServiceContract(Namespace="https://tempuri.org")]

public class WebService : System.Web.Services.WebService

{   

   

    [WebMethod]

    [OperationContract]

    public string HelloWorld(string name)

    {

        return string.Format("Hello, {0}",name);

    }

}

   

This change allows you to continue using an ASMX file that points to your code-behind to continue using the ASMX framework, or introduce a SVC file that enables WCF hosting. You also need to introduce into your config file the system.serviceModel configuration data:

<?xml version="1.0"?>

<configuration>

   

  <system.serviceModel>

    <services>

      <service name="WebService" behaviorConfiguration="returnFaults">

        <endpoint binding="basicHttpBinding" contract="WebService"/>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="returnFaults">

          <serviceDebug includeExceptionDetailInFaults="true"/>

          <serviceMetadata httpGetEnabled="true"/>

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

 

Once you are confident that WCF is kicking ASMX's butt in performance and manageability, the next step is to cut over to WCF. Just remap the BuildProvider for ASMX to use System.ServiceModel instead.

  <system.web>

    <compilation debug="true">

      <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>

 

If you want to confirm that this is, in fact, using WCF now instead of ASMX, just point to the WSDL endpoint and notice that the friendly description page directs to use svcutil to generate proxy… and of course, we all know that svcutil is the WCF version of wsdl.exe!

Thanks to Ram Poornalingam for pointing out this really cool capability.