Using reflection to call an ASP.NET web service

2020-05-24 05:42发布

Say I have an ASMX web service, MyService. The service has a method, MyMethod. I could execute MyMethod on the server side as follows:

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

I need to do similar, with service and method not known until runtime.

I'm assuming that reflection is the way to go about that. Unfortunately, I'm having a hard time making it work. When I execute this code:

Type.GetType("MyService", true);

It throws this error:

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

Any guidance would be appreciated.

8条回答
姐就是有狂的资本
2楼-- · 2020-05-24 05:45

Here's a quick answer someone can probably expand on.

When you use the WSDL templating app (WSDL.exe) to genereate service wrappers, it builds a class of type SoapHttpClientProtocol. You can do it manually, too:

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

I haven't tested this code but I imagine it should work stand-alone without having to run the WSDL tool.

The code I've provided is the caller code which hooks up to the web service via a remote call (even if for whatever reason, you don't actually want it to be remote.) The Invoke method takes care of packaging it as a Soap call. @Dave Ward's code is correct if you want to bypass the web service call via HTTP - as long as you are actually able to reference the class. Perhaps the internal type is not "MyService" - you'd have to inspect the control's code to know for sure.

查看更多
The star\"
3楼-- · 2020-05-24 05:45

@Kibbee: I need to avoid the HTTP performance hit. It won't be a remote call, so all of that added overhead should be unnecessary.

@Daren: I definitely agree with that design philosophy. The issue here is that I'm not going to be in control of the service or its underlying business logic.

This is for a server control that will need to execute against an arbitrary service/method, orthogonally to how the web service itself is implemented.

查看更多
Bombasti
4楼-- · 2020-05-24 05:50

@Radu: I'm able to create an instance and call the method exactly like that. For example, if I have this 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";
  }
}

I'm able to call it from an ASPX page's codebehind like this:

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

Are you saying that shouldn't work?

查看更多
smile是对你的礼貌
5楼-- · 2020-05-24 05:51

Although I don't know why Reflection is not working for you there (I assume the compiler might be creating a new class from your [WebService] annotations), here is some advice that might solve your problem:

Keep your WebService simple, shallow, in short: An implementation of the Facade Pattern.

Make your service delegate computation to an implementation class, which should easily be callable through Reflection. This way, your WebService class is just a front for your system - you can even add an email handler, XML-RPC frontend etc., since your logic is not coupled to the WebService, but to an actual business layer object.

Think of WebService classes as UI layer objects in your Architecture.

查看更多
一夜七次
6楼-- · 2020-05-24 05:58

Although I cannot tell from your post:

One thing to keep in mind is that if you use reflection, you need to create an instance of the autogenerated webservice class(the one created from your webservice's WSDL). Do not create the class that is responsbile for the server-side of the service.

So if you have a webservice

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

you cannot reference that assembly in your client and do something like:

WebService1  ws = new WebService1 ();
ws.SomeMethod();
查看更多
成全新的幸福
7楼-- · 2020-05-24 05:59

// Try this ->

    Type t = System.Web.Compilation.BuildManager.GetType("MyServiceClass", true);
    object act = Activator.CreateInstance(t);                
    object o = t.GetMethod("hello").Invoke(act, null);
查看更多
登录 后发表回答