Introduction
After many hours of struggle, I finally got a WCF service that was written in .NET 4.0 to be able to be consumed by my legacy ASP.NET app that is still in .NET 1.1. I used the word "struggle" because I literally went through many of dispersible web postings out there, one blog here, one article there, and something somewhere else, very time-consuming and exhaustive; I believe the need for doing what I did is still out there; so to keep myself afresh with what I've done and to help others avoid experiencing the same pain I just went through, I decided it is worthwhile to wire all these up into one piece and deposit it to CodeProject.com for a broader audience. There is nothing academic about this - the things I covered here were basically imprinted with my sweaty fingerprints all over the places.
Background
With the WCF Service templates (one for WCF service application and one for WCF class library) readily available inside the VS2010, creating a WCF service is simple and straightforward; that was what I did when I first started it: I used the WCF Service application project template and instantly I had an IService
interface and a Service1.svc, as well as automatically configured web.config. A few minutes later, I published the Service1
and was able to use it to call GetData()
method from a web project inside the solution. With that Service1.svc running on IIS, I went into my legacy .NET 1.1 project and set a web reference to it. Not surprisingly, after I called the same GetData()
method from inside the .NET 1.1 app, troubles started to line up in my face. First, it was a VS2010 JIT debugger dialog box popping up, as shown here:
if I clicked on “Yes” to debug, I encountered the obscure “AccessViolationException Unhandled” error dialog.
and drilled down to the View Detail, then I got this, “Attempted to read or write protected memory. This is often an indication that other memory is corrupt”. Very scary stuff! Got out there fast and then I ran into this “The underlying connection was closed: An unexpected error occurred on a receive” when I returned to the ASP.NET 1.1 app:
Create Backward Compatible Web Service
So what did I miss? After some readings from MSDN site and social MSDN site, two aspects of this project came into focus: the XmlSerializerFormat
attribute on the ServiceContract
and the A (address) B (binding) C (contract) settings in the web.config of the WCF project. The keys were to configure these things so that the WCF service would become ASMX service or traditional web service, which of course was the only meal that an ASP.NET 1.1 old folk could take in from the modern food chain like WCF.
IIS Setup
I am running IIS 7 on a Windows Server 2003 box so it was easy to setup multiple sites running on different versions of .NET Frameworks. For other OS, like Windows XP Pro, the only way to run multiple sites is to stop and start a site one at a time.
First, I created a new site on IIS7 called WcfHost
and I had to assign a different TCP port number to it, in this case, a port 8088 (for no particular reason but sounding good to me). My ASP.NET 1.1 app was already taking the default port 80. Later, when I needed to reference to the WCF web service published at WcfHost
, I would reference it beginning with http://localhost:8088/WcfHost/.....
Creating the Service
To make a WCF service to be consumable by a .NET 1.1 app, the only thing that is different from creating a regular WCF service, from coding side, is adding an XmlSerializerFormat
attribute to the service interface. So instead of this:
[ServiceContract]
public interface IService1{…}
I used this:
[ServiceContract, XmlSerializerFormat]
public interface IService1 {…}
That was all it took from the coding side. Now the other key part was to make some changes on the Web.config file of the WCF service project.
Configuring ABC
Before any modification was done, the Web.config that was automatically thrown in when I created my WcfToASMX
WCF service app project using the WCF service app template looked like this:
="1.0"
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Following the article from MSDN and a blog from Social.MSDN.COM, I made the necessary entries and modifications to the file and now it looks like this:
="1.0"
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfToAsmx.Service1" behaviorConfiguration="asmx">
<endpoint address="basic" binding="basicHttpBinding"
contract="WcfToAsmx.IService1" ></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="asmx">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
The bolded or highlighted areas are all the changes needed in Web.Config of WCF service project, and the Service1.svc is now ready to be published to IIS7 to be consumed by clients of all ages (from .NET 4.0 down to .NET 1.1).
Publishing the Service
Publishing a WCF service to IIS was a wizard-click away. I clicked on the Publish (service project name, in my case WcfToAsmx
) link under the Build menu, and a “Publish Web” wizard dialog showed up. I left the Publish
method as it was default, “Web Deploy”, and entered the Service URL: http://localhost:8088, which was setup earlier in IIS; then I entered the Site/Application: “WcfHost/Test/CP/WcfToAsmx”, and checked the “Mark as IIS application on destination” checkbox. Clicked on Publish button and done. Since the “Mark as IIS app” checkbox was checked, I did not have to create any of these folders “Test/CP/WcftoAsmx”; the IIS created automatically for me as long as there was the website “WcfHost
” already existing.The actual publishing screen was captured and shown here:
Rendering of the Service1.svc
To make sure the WCF service is functioning, I went into the IIS7 admin console and browsed the Service1.svc. A callable service should render itself to browser looking like the screen here:
Consume The Service
Now, time travel back a decade and launch that old mighty VS2003 to create an ASP.NET 1.1 client app. There is not much to do here – all I need is to add a web service reference to the project, just like adding any other web service reference, except the service URL would look like this, http://localhost:8088/Test/CP/WcfToAsmx/Service1.svc, instead of this http://localhost:8088/Test/CP/WcfToAsmx/Service1.asmx. The rest is exactly the same as you would be dealing with a traditional web service. There is nothing needed to add or change made to client’s web.config or app.config file.
Summary
It is actually very simple to make a backward compatible WCF service that is consumable by legacy .NET 1.1 client. The key changes needed for such a WCF service project are:
- Add a
XmlSerializerFormat
attribute to the ServiceContract
while building a service interface. - Add a service endpoint to the Web.Config and specify the address=”
basic
” and binding=”basicHttpBinding
”.
Acknowledgements
These two sources were my major readings during my search for the solution:
- MSDN article published on 2010-06-09 at http://msdn.microsoft.com/en-us/library/ms751433.aspx
- Jay R. Wren’s answers to user Bernie Almosni on 2007-03-15 at http://social.msdn.microsoft.com/forums/en-US/wcf/thread/1f8c7fe9-784c-4beb-8d0f-060bf8bfc24f
History
- First submitted on 2/25/2011