2008-09-15 117 views
7

假設我有一個ASMX Web服務MyService。該服務有一個方法MyMethod。我可以在服務器端執行MyMethod,如下所示:使用反射調用ASP.NET Web服務

MyService service = new MyService(); 
service.MyMethod(); 

我需要做類似的事情,服務和方法直到運行時才知道。

我假設反射是有關的方式。不幸的是,我正在努力工作。當我執行此代碼:

Type.GetType("MyService", true); 

它拋出這個錯誤:

Could not load type 'MyService' from assembly 'App_Web__ktsp_r0, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

任何指導,將不勝感激。

回答

2

我不確定這是否是最好的解決方法。對我來說最明顯的方法是創建一個HTTP請求,並使用實際的HTTP GET或POST調用web服務。使用您的方法,我不完全確定如何設置發送到Web服務的數據。我已經添加了一些示例代碼在VB.Net

Dim HTTPRequest As HttpWebRequest 
Dim HTTPResponse As HttpWebResponse 
Dim ResponseReader As StreamReader 
Dim URL AS String 
Dim ResponseText As String 

URL = "http://www.example.com/MyWebSerivce/MyMethod?arg1=A&arg2=B" 

HTTPRequest = HttpWebRequest.Create(URL) 
HTTPRequest.Method = "GET" 

HTTPResponse = HTTPRequest.GetResponse() 

ResponseReader = New StreamReader(HTTPResponse.GetResponseStream()) 
ResponseText = ResponseReader.ReadToEnd() 
1

雖然我不知道爲什麼反思是不是爲你工作有(我假設編譯器可能會產生從[WebService]註釋的新類),在這裏是一些建議,可以解決您的問題:

保持您的WebService簡單,淺,簡而言之:實現門面模式

將您的服務委託計算轉換爲實現類,該實現類應該很容易通過反射來調用。這樣,您的WebService類僅僅是您的系統的前臺 - 您甚至可以添加電子郵件處理程序,XML-RPC前端等,因爲您的邏輯不是耦合到WebService,而是耦合到實際的業務層對象。

將WebService類視爲架構中的UI層對象。

0

@Kibbee:我需要避免HTTP性能下降。它不會是一個遠程調用,所以所有增加的開銷應該是是不必要的。

@達人:我絕對同意這種設計理念。這裏的問題是我不會控制服務或其底層的業務邏輯。

這是針對a server control需要針對任意服務/方法執行的,與Web服務本身的實現方式正交。

0

雖然我不能從您的文章說:

有一點要記住的是,如果你使用反射,你需要創建一個自動生成的Web服務類的一個實例(從您的Web服務的WSDL創建的)。不要創建負責服務器服務器端的類。

所以,如果你有一個web服務

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

你不能引用裝配在客戶端和做類似:

WebService1 ws = new WebService1(); 
ws.SomeMethod(); 
0

@Radu:我能創建一個實例,並調用該方法完全如此。舉例來說,如果我有這樣的ASMX:

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

我能夠從一個ASPX頁面的代碼隱藏調用它是這樣的:

MyService service = new MyService(); 
Response.Write(service.HelloWorld());

你是說,不應該工作?

+0

該宏將會 「工作」,但可能並不像你想讓它。它將返回「Hello World」字符串,但該方法將在客戶端本地執行,而不是在服務器上進行。 – Radu094 2008-09-15 20:17:57

1

下面是一個很快可以解答的問題。

當您使用WSDL模板應用程序(WSDL.exe)來生成服務包裝器時,它會構建一個SoapHttpClientProtocol類型的類。你可以做手工,太:

public class MyService : SoapHttpClientProtocol 
{ 
    public MyService(string url) 
    { 
     this.Url = url; 
     // plus set credentials, etc. 
    } 

    [SoapDocumentMethod("{service url}", RequestNamespace="{namespace}", ResponseNamespace="{namespace}", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] 
    public int MyMethod(string arg1) 
    { 
     object[] results = this.Invoke("MyMethod", new object[] { arg1 }); 
     return ((int)(results[0])); 
    } 
} 

我沒有測試代碼,但我想它應該獨立工作,而不必運行的WSDL工具。

我提供的代碼是通過遠程調用連接到Web服務的調用者代碼(即使出於任何原因,您實際上並不希望它是遠程調用).Invoke方法負責將其打包爲肥皂呼叫。 @Dave Ward的代碼是正確的,如果你想通過HTTP繞過Web服務調用 - 只要你真的能夠引用這個類。也許內部類型不是「MyService」 - 你必須檢查控件的代碼才能確定。

0

我回頭看了這個問題,我認爲你所面對的是ASMX代碼將被內置到一個隨機名稱的DLL中,作爲動態編譯站點的一部分。默認情況下,查找類型的代碼將僅搜索自己的程序集(另一個App_Code DLL,通過收到的錯誤的外觀)和核心庫。您可以爲GetType()提供特定的程序集引用「TypeName,AssemblyName」,但在自動生成的程序集的情況下這是不可能的,這些程序集在每次重新編譯後都有新的名稱。

解決方案....我沒有這樣做過自己,但我相信,你應該能夠使用這樣的事情:

System.Web.Compilation.BuildManager.GetType("MyService", true) 

爲BuildManager知道它創造了的DLL和知道去哪裏看。

我想這實際上並不是與Web服務有關,但如果它是您自己的代碼,Daren對於Facade模式的權利。

1

//試試這個 - >

Type t = System.Web.Compilation.BuildManager.GetType("MyServiceClass", true); 
    object act = Activator.CreateInstance(t);     
    object o = t.GetMethod("hello").Invoke(act, null);