Question

I'm facing an issue with different versions of a Web Service.

Because there are several versions of the Web service, sometimes the parameters are changed and/or WebMethods are added and removed.

I want to have a single asmx file, but depending on the client installation (the version they are running), be able to change the code behind of the asmx at runtime.

Instead of having different asmx per version, just have one asmx file that dynamically can load the code behind with the accurate version. In this case I do have a V1Methods.cs, V2Methods.cs, V10Methods.cs

<%@ WebService Language="C#"  Class="DynamicClass" %>

If the customer is running Version2, the asmx code behind class should be V2Methods.cs and so on.

Is it possible?

Was it helpful?

Solution 2

OK - I have a possible solution for you that is not award-winning for elegance but I've just tested it and it works.

You can expose one WebMethod that returns object and takes a params object[] parameter, allowing you to pass whatever you like to it (or nothing) and return whatever you want. This compiles to legal WSDL using the 'anyType' type.

If you can identify which actual method to call based on the number and datatype of parameters passed to this method, you can call the appropriate method and return whatever value you want.

The service: -

[WebMethod]
public object Method(params object[] parameters)
{
    object returnValue = null;

    if (parameters != null && parameters.Length != 0)
    { 
        if (parameters[0].GetType() == typeof(string) && parameters[1].GetType() == typeof(int))
        {
            return new ServiceImplementation().StringIntMethod(parameters[0].ToString(), Convert.ToInt32(parameters[1]));
        }
        else if (parameters[0].GetType() == typeof(string) && parameters[1].GetType() == typeof(string))
        {
            return new ServiceImplementation2().StringStringMethod(parameters[0].ToString(), parameters[1].ToString());
        }
    }

    return returnValue;
}

My test service implementation classes: -

public class ServiceImplementation
{
    public string StringIntMethod(string someString, int someInt)
    {
        return "StringIntMethod called";
    }
}

public class ServiceImplementation2
{
    public float StringStringMethod(string someString, string someOtherString)
    {
        return 3.14159265F;
    }
}

An example of use: -

    var service = new MyTestThing.MyService.WebService1();

    object test1 = service.Method(new object[] { "hello", 3 });
    Console.WriteLine(test1.ToString());

    object test2 = service.Method(new object[] { "hello", "there" });
    Console.WriteLine(test2.ToString());

I've tested this and it works. If you're interested, the WSDL that "Method" generates: -

POST /test/WebService1.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/Method"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <Method xmlns="http://tempuri.org/">
      <parameters>
        <anyType />
        <anyType />
      </parameters>
    </Method>
  </soap:Body>
</soap:Envelope>

Incase you're wondering, yes I am bored at work and I'm in the mood for helping people :)

OTHER TIPS

In short no, that is not possible. I was going to suggest using the webservice as a facade but by the sounds of it the method signatures on each version are different, which would make that more difficult.

If the client application is dependent on a particular version of your webservice, can't you just deploy all versions of your service with different names (i.e. servicev1.asmx, servicev2.asmx etc), and add some config to your client to tell it which one to call ?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top