2009-05-30 50 views
7

我在C#ASP.NET項目中使用了一個類,允許以某種隨機腳本語言編寫的腳本動態地公開webservice方法 - 換句話說,腳本應該能夠公開一個方法任何帶有任何簽名的名字(只要它是有效的),通過這個SOAP接口(可以隨意添加和刪除它們,不需要更改硬代碼),因此我需要能夠創建一個C#中的webservice類,同時能夠在運行時動態添加和刪除方法。Dynamic C#.NET Webservice

現在,我已經能夠提出的最佳方案是(運行時)生成代表Web服務的C#代碼,使用System.Reflection.Emit進行編譯,然後在運行時加載程序集 - 所有每當腳本添加或刪除服務的方法(不應該經常發生,請注意)。

有沒有人比這更好的主意?

回答

5

您可以使用SoapExtensionReflector類修改WSDL。從Kirk Evans Blog

當您的類型被反映出來爲您的服務提供WSDL定義時,會調用SoapExtensionReflector。您可以利用此類型來攔截反射調用並修改WSDL輸出。

以下示例刪除第一方法出2 web服務方法:

[WebService(Namespace = "http://tempuri.org/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
[System.ComponentModel.ToolboxItem(false)] 
public class Service1 : System.Web.Services.WebService 
{ 
    [WebMethod] 
    public string HelloWorld() 
    { 
     return "Hello World"; 
    } 

    [WebMethod] 
    public int Multiply(int a, int b) 
    { 
     return a * b; 
    } 
} 

創建從SoapExtensionReflector繼承的類:

namespace TestWebservice 
{ 
    public class MyReflector : SoapExtensionReflector 
    { 
     public override void ReflectMethod() 
     { 
     //no-op 
     } 

     public override void ReflectDescription() 
     { 
     ServiceDescription description = ReflectionContext.ServiceDescription; 
     if (description.PortTypes[0].Operations.Count == 2) 
      description.PortTypes[0].Operations.RemoveAt(0); 
     if (description.Messages.Count == 4) 
     { 
      description.Messages.RemoveAt(0); 
      description.Messages.RemoveAt(0); 
     } 
     foreach (Binding binding in description.Bindings) 
     { 
      if (binding.Operations.Count == 2) 
       binding.Operations.RemoveAt(0); 
     } 
     if (description.Types.Schemas[0].Items.Count == 4) 
     { 
      description.Types.Schemas[0].Items.RemoveAt(0); 
      description.Types.Schemas[0].Items.RemoveAt(0); 
     } 
     } 
    } 
} 

此添加到配置/ System.Web程序部在web.config中:

<webServices> 
    <soapExtensionReflectorTypes> 
     <add type="TestWebservice.MyReflector, TestWebservice" /> 
    </soapExtensionReflectorTypes> 
</webServices> 

這應該給你一個動態從WSDL文檔中刪除方法的出發點。如果禁用,您還需要從Web方法中拋出NotImplementedException。

最後,您需要禁用不帶?WSDL參數調用.asmx端點生成的Web服務文檔。將wsdlHelpGenerator元素的href屬性設置爲某個URL。您可以使用DefaultWsdlHelpGenerator.aspx作爲您自己的文檔處理程序的起點。請參閱XML Files, August 2002中有關Web服務文檔的問題。

1

它是否必須是一個SOAP接口?這聽起來像它可能更適合於基於路由/ REST/etc的API。你可以很容易地在ASP.NET MVC中做一些事情(用自定義的IController.Execute方法來解決對方法的操作)(事實上,我正在爲some of my own code做一些非常類似的事情)。

例如,你可能有路線:

http://myserver/myservice/mymethod 

接受(或者在體內或參數)有效負載(參數),並返回結果的響應。在非MVC中,您應該能夠使用通配符映射的通用處理程序執行類似的操作。

+0

感謝您的快速響應 - 不幸的是它必須是SOAP。我直到現在都在使用XMLRPC,但與不願使用XMLRPC的第三方接口意味着我必須用SOAP來玷污它。 :( – 2009-05-30 22:24:37

+0

嗯......「祝你好運...」 – 2009-05-30 22:25:59

2

XMLRPC已經死了,不是嗎?

SOAP意味着一個WSDL。如何動態生成WSDL?

你應該看看使用WCF。我希望你能夠控制生成WSDL(和其他元數據)的過程,但你也應該能夠控制傳入消息的處理。特別是,你將能夠檢查傳入的消息以確定要運行的腳本,傳遞什麼參數等

2

您可以創建與xs:any的輸入和輸出類型的WCF服務和處理傳入的請求爲原料Message。這將允許您接受任何類型的數據並返回任何類型的數據。您不會使用數據合同或靜態類型,只需要輸入Message和輸入Message即可。

這種方法的問題是,從WSDL生成代理確實沒有什麼幫助消費者提供包裝來調用方法。提供方法可接受的數據將需要手動滾動的數據類型等,這並不困難,但它不像一個硬性的打字合同那麼直觀。