Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Create a WCF Service that can be Consumed by Legacy .NET 1.1 Web App

4.56/5 (5 votes)
25 Feb 2011CPOL6 min read 39K   337  
Exposing WCF Service created in .NET 4.0 to .NET 1.1 client

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:

VS2010 JIT Debugger Dialog

if I clicked on “Yes” to debug, I encountered the obscure “AccessViolationException Unhandled” error dialog.

Access Violation error

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:

Client side error

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:

C#
[ServiceContract]
public interface IService1{…}

I used this:

C#
[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:

XML
<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information,
          set the value below to false and remove the
          metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for
          debugging purposes, set the value below to true.
          Set to false before deployment to avoid 
          disclosing exception information -->
          <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:

XML
<?xml version="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">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint 
          above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <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:

Publish WCF service

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:

a functioning Service1.svc

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:

  1. Add a XmlSerializerFormat attribute to the ServiceContract while building a service interface.
  2. 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:

  1. MSDN article published on 2010-06-09 at http://msdn.microsoft.com/en-us/library/ms751433.aspx
  2. 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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)