Preserving ASMX web service contracts in WCF

by jk 18. June 2007 00:54

Recently, I had an interesting experience regarding trying to preserve the contents of an ASMX/WSE3 web service contract (using C#, and Xml Serialization attributes) in a WCF service.   The mantra of SOAP (and COM/DCOM) is to define a contract as your abstractraction, and then you can swap out implementations w/o affecting the caller.

So here was my interface (.NET 2.0, C#) for the ASMX endpoint:

public interface IFooService

{

                [WebMethod]

                [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]

                FooResponse Foo(FooRequest request);

}

As you can see here, I asked the ASMX plumbing *not* to wrap my request/response in an additional element since I already had a class defined to be my message contract.

However, when I decided to sprinkle the WCF pixie-dust attributes on my interface:

public interface IFooService

{

                [OperationContract] //pixie-dust

                [WebMethod]

                [SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]

                FooResponse Foo(FooRequest request);

}

exposed it in WCF via basicHttpBinding, and pointed my clients talking ASMX I started receiving the dreaded “Contract Mismatch” exception/fault.

After some logging/tracing with WCF Service Trace Viewer and log4net, I found the problem.  By default, WCF wraps the soap parameters.  In the example above, the ASMX message looked something like this:

<soap:Envelope …(a whole pile of namespaces)>

                <soap:Body>

                                <FooRequest>

                                                <!-- content omitted for brevity -->

                                </FooRequest>

                </soap:Body>

</soap:Envelope>

But the WCF infrastructure was looking for a wrapped parameter (default behavior which I didn’t account for)

<soap:Envelope …(a whole pile of namespaces)>

                <soap:Body>

                                <request>

                                                <FooRequest>

                                                                <!-- content omitted for brevity -->

                                                </FooRequest>

                                </request>

                </soap:Body>

</soap:Envelope>

The way to change this default behavior is by creating a MessageContract and setting IsWrapped = false.  WCF was treating my data contracts (FooRequest FooResponse).

The takeaway; WCF wraps messages by default, use a tool to trace your SOAP messages to figure out what's on the wire, and it is typically easier to write something new than change something existing :)

jk

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen