views:

47

answers:

1

I am trying to access an old ASMX webservice using WCF by calling the ChannelFactory.CreateChannel() method.

If the web service is created by WCF, everything is straightforward. I can instantiate the proxy client generated by the svcutil tool, or manually call the ChannelFactory.CreateChannel() method. Afterwards, I can call the web service methods the same way for both scenarios.

But if the web service is of the old ASMX variety, I can still instantiate the proxy either way, but I am unable to call the same web service method.

For example, assume this basic WCF web service interface:

[ServiceContract]
public interface IWebService
{
    [OperationContract]
    string HelloWorld();
}

After using svcutil to generate the proxy, I can call HelloWorld() one of 2 ways:

WebServiceClient proxy = new ServiceReference.WebServiceClient();
textBox1.Text += proxy.HelloWorld();

or:

ChannelFactory<ServiceReference.IWebService2> cfactory = 
    new ChannelFactory<ServiceReference.IWebService>("BasicHttpBinding_IWebService");
ServiceReference.IWebService proxy = cfactory.CreateChannel();
((IClientChannel)proxy).Open();
textBox1.Text += proxy.HelloWorld();

Now assume this ASMX web service:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
    public WebService() {   }

    [WebMethod]
    public string HelloWorld()
    {
        return "Hello World";
    }
}

Calling HelloWorld() using the SoapClient generated by svcutil tool is nearly the same as if it were a WCF web service:

WebServiceSoapClient proxy = new ServiceReference.WebServiceSoapClient();
textBox1.Text += proxy.HelloWorld();

But trying to call HelloWorld() if you create the channel yourself and you will get an error:

ChannelFactory<ServiceReference.WebServiceSoap> cfactory =
     new ChannelFactory<ServiceReference.WebServiceSoap>("WebServiceSoap");
ServiceReference.WebServiceSoap proxy = cfactory.CreateChannel();
((IClientChannel)proxy).Open();
textBox1.Text += proxy.HelloWorld();

The error is "No overload for method HelloWorld takes 0 arguments".

It appears it is because the HelloWorld method in the autogenerated interface (ServiceReference.WebServiceSoap) takes an argument of type ServiceReference.HelloWorldRequest.

So in the end, I was only able to make it work by looking through the svcutil generated code and change my implementation to this:

ChannelFactory<ServiceReference.WebServiceSoap> cfactory = 
    new ChannelFactory<ServiceReference.WebServiceSoap>("WebServiceSoap");
ServiceReference.WebServiceSoap proxy = cfactory.CreateChannel();
((IClientChannel)proxy).Open();
ServiceReference.HelloWorldRequest inValue = 
    new WCFConsumeWebServices.ServiceReference.HelloWorldRequest();
inValue.Body = new WCFConsumeWebServices.ServiceReference.HelloWorldRequestBody();
ServiceReference.HelloWorldResponse retVal = proxy.HelloWorld(inValue);
textBox1.Text += retVal.Body.HelloWorldResult;

Is this how it is suppose to be?

For one type of basic http web service, we get to use virtually the same code to call a method, but for another we need to muck through the generated proxy code and have different implementation depending on how you open the channel ?

+1  A: 

Offhand, I don't know why, but WCF appears to be using a Message Contract when it talks to your ASMX service. Have you posted the entire service?

John Saunders
Post the entire service ?The above code IS the entire asmx webservice implementation (the WebService.cs file).The asmx file has only one line:<%@ WebService Language="C#" CodeBehind="~/App_Code/WebService.cs" Class="WebService" %>It has only one webmethod HelloWorld() which takes no arguments and returns the string "Hello World".The problem is that the autogenerated proxy code (from svcutil) has an interface which does not have a HelloWorld method that takes no arguments, even though the actual webservice does.
Buma
@Buma: please do **NOT** post long code pieces into comments - those aren't legible. Please **update** your original question by editing it - thanks.
marc_s
Yes, this behavior seems to be the way it works - not sure if there are any particular reasons for this (probably there are).
marc_s
@Buma: Most likely, if you had a webmethod that accepted an object of a class, and returned one, you'd see something closer to what you'er accustomed to.
John Saunders
If that is the way it is suppose to be, I would say it is very disappointing. Requiring users to muck through the generated proxy code just to run a simple method if you open your own channel doesn't seem to make a lot of sense. It would probably get much more complicated as the webservice gets more complex.
Buma