2013-11-28 27 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

相關問題