2008-09-15 121 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);