2013-11-28 24 views
0

我正面临着不同版本的Web服务的问题。如何动态更改类后面的WebService代码?

由于Web服务有多个版本,有时会更改参数和/或添加和删除WebMethods。

我想要一个asmx文件,但根据客户端安装(它们正在运行的版本),能够在运行时更改asmx背后的代码。

而不是每个版本有不同的asmx,只需要一个asmx文件,它可以动态地将代码加载到准确的版本中。在这种情况下,我有一个V1Methods.cs,V2Methods.cs,V10Methods.cs

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

如果客户正在运行版本2,隐藏类的ASMX代码应该是V2Methods.cs等。

可能吗?

+0

如何你知道你的客户端运行的是什么版本吗?典型的REST API将使用URL方案来区分版本。 – Alexandre

+0

在这种情况下,将会有一个配置文件,在安装过程中,用户将被要求输入产品版本(与API版本或WSDL绑定)。也就是说,我试图通过拥有一个EndPoint来实现这一点。主要的问题是版本之间的WSDL有巨大的变化。 –

+1

ASMX是一项传统技术,不应该用于新开发。 WCF或ASP.NET Web API应该用于Web服务客户端和服务器的所有新开发。一个暗示:微软已经在MSDN上退役了[ASMX Forum](http://social.msdn.microsoft.com/Forums/en-US/asmxandxml/threads)。 –

回答

1

好的 - 我有一个可能的解决方案,它不是屡获殊荣的优雅,但我刚刚测试过它,它的工作原理。

您可以公开一个WebMethod,该WebMethod返回对象并获取params对象[]参数,从而允许您将任何喜欢的东西传递给它(或者什么都不),并返回任何你想要的东西。这使用'anyType'类型编译为合法的WSDL。

如果您可以根据传递给此方法的参数的数量和数据类型来确定要调用哪个实际方法,则可以调用相应的方法并返回所需的任何值。

服务: -

[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; 
} 

我的测试服务实现类: -

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; 
    } 
} 

使用的例子: -

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()); 

我测试过这一点,它的工作原理。如果你有兴趣,该WSDL是“方法”产生: -

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> 

柜面你想知道的,是我在工作无聊,我的心情帮助人们:)

+0

感谢您花时间在这里,我认为这种方法可能会起作用,并且我可以使用AST编写一些脚本来生成带有参数数组的WebMethods。实际上取决于参数。由于我将有一个配置文件的版本,我知道要调用什么实现。谢谢。 –

+0

经过一番测试,我认为问题更大。通过查看两个不同版本的代理(v1和v3),我可以看到在V3中一些WebMethods已被删除,并在V1中使用。如果我使用版本3中的所有方法,则其他一些方法将不可用。由于客户端被设计为消耗当前API中的某些特定方法,因为每个版本都会因为删除或添加WebMethods而增加复杂性,所以除了在运行时生成代理外,没有其他选择。 –

3

总之不,那是不可能的。我打算建议使用webservice作为外观,但通过它的声音,每个版本的方法签名是不同的,这会使得更加困难。

如果客户端应用程序依赖于您的web服务的特定版本,是不是可以用不同的名称(例如servicev1.asmx,servicev2.asmx等)来部署所有服务版本,并将一些配置添加到您的客户端告诉它哪一个要调用?

+0

你好,这可能是另一种选择。这将是一个问题,但如果客户端被设计为总是寻找特定的服务,那么这种方法将无法正常工作(我的意思是,如果客户端被设计为始终发现服务名称)。由于Web服务被不同技术中的多个客户使用,我仍然会对其进行测试。感谢您的回答,我非常感谢。 –

+0

实际上,我也在考虑创建一种路由器,该路由器应该使用暴露的WebMethods加载当前类,但要公平,我还没有弄清楚如何去做。 –

+0

客户被设计为“总是寻找特定的服务” - 这里的问题是您无法访问其源代码? – sh1rts

相关问题