How to use .asmx extension to handle WCF requests?
For backward compatibility, WCF supports easy server-side migration from ASMX to WCF. This is good news for existing ASMX customers. Generally, the clients of ASMX may have server Urls hard-coded with the extension “.asmx”. For example, here is a sample Url:
https://www.myserver.com/foo/MyService.asmx
After installing WCF on the box, you can let WCF to handle the same client requests. Here are the steps about how to achieve this:
Replace BuildProvider for ASMX
You need to use the WCF service build provider for .asmx extension by seting the following in the web.config file of your virtual application:
<system.web>
<compilation>
<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>
When WCF is running in the Mixed Transport mode (instead of AspNetCompatibility mode), WCF would intercept the request based on the BuildProvider information for the extension.
Replace HttpHandler for ASMX
If you are running WCF in AspNetCompatibility mode, you would also need to change the HttpHandler s for .asmx to the WCF HttpHandler. On IIS6, you just need to have something as following in your config:
<system.web>
<httpHandlers>
<remove path="*.asmx" verb="*"></remove>
<add path="*.asmx" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
validate="false" />
</httpHandlers>
</system.web>
On IIS7, things are different. IIS7 introduces two different HTTP pipelines: Integrated and Classic. The latter works similar as IIS6 in the way that all of the managed requests go through the ASP.NET ISAPI filter. When this happens, the HttpModules and HttpHandlers defined in web.config files would be invoked for the corresponding requests.
When the virtual application is running in the Integrated mode, however, the modules and handlers defined in web.config files under the <system.web> section are totally ignored. All of the requests are handled straightforward by IIS7. So you need to make sure that you have integrated handlers defined for the corresponding extensions. We can set the following in the web.config of the virtual application to achieve this:
<system.webServer>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated"/>
<add name="MyNewAsmxHandler" path="*.asmx" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
</handlers>
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
The section <system.webServer> is actually rooted in %windir%\system32\inetsrv\config\applicationhost.config instead of in the root web.config in %windir%\Microsoft.Net\Framework{64}\v2.0.50727\config. The <remove> element takes the “name” as the key instead of the “path” as we did to the <system.web> section. You must specify “validateIntegratedModeConfiguration” to false to make IIS happy.
Correct SOAP Actions
Once you configured above settings, you can create a .asmx file which looks exactly as a .svc file. For example, you can have the following content:
<% @ServiceHost language = "c#" Factory="HelloWorld.SimpleServiceHostFactory" %>
Now you can browse your service with an .asmx extension. At this point, all requests will go through happily into WCF channel stack.
One last thing that you need to be aware is that you need to make sure your WCF service is backward compatible to ASMX so that ASMX clients can communicate with it. Basically you need to use the interoperable binding such as BasicHttpBinding. And you need to make sure the request/response SOAP actions are expected for ASMX clients. Here is an example:
[ServiceContract(Name = "RequestReplyService", Namespace = "https://myoldasmxworld.org/")]
public interface IRequestReplySyncServiceAsmx
{
[OperationContract(IsOneWay = false, Action = "https://myoldasmxworld.org/HelloRequestReply")]
string HelloRequestReply(string text);
}
It is compatible to the following ASMX web service:
[WebService(Name = "MyAsmxService", Namespace = "https://myoldasmxworld.org/")]
public class AsmxRequestReplyService
{
[WebMethod]
public string HelloRequestReply(string text)
{
// Implementation
}
}
Comments
Anonymous
October 16, 2008
PingBack from http://pittcrew.net/geekblog/2008/10/16/wcf-services-with-the-asmx-extension/Anonymous
February 17, 2011
I tried the above code and works like a charm. However, I now need to convert my web service project to framework 4.0. What changes do I need to make for converting it?Anonymous
September 24, 2013
Here is the configuration for Framework 4.5 (I assume this will work in 4.0 also). <system.web> <compilation debug="true" targetFramework="4.5"> <buildProviders> <remove extension=".asmx"/> <add extension=".asmx" type="System.ServiceModel.Activation.ServiceBuildProvider, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/> </buildProviders> </compilation> <httpRuntime targetFramework="4.5" /> </system.web> <system.webServer> <handlers> <remove name="WebServiceHandlerFactory-Integrated-4.0" /> <add name="MyNewAsmxHandler" path=".asmx" verb="" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers> </system.webServer>