Using reflection to call an ASP.NET web service

前端 未结 8 1417
一向
一向 2021-02-04 17:25

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          


        
相关标签:
8条回答
  • 2021-02-04 17:44

    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.

    0 讨论(0)
  • 2021-02-04 17:49

    I looked back at this question and I think what you're facing is that the ASMX code will be built into a DLL with a random name as part of the dynamic compilation of your site. Your code to look up the type will, by default, only search its own assembly (another App_Code DLL, by the looks of the error you received) and core libraries. You could provide a specific assembly reference "TypeName, AssemblyName" to GetType() but that's not possible in the case of the automatically generated assemblies, which have new names after each recompile.

    Solution.... I haven't done this myself before but I believe that you should be able to use something like this:

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

    as the BuildManager is aware of the DLLs it has created and knows where to look.

    I guess this really doesn't have to do with Web Services but if it were your own code, Daren's right about Facade patterns.

    0 讨论(0)
  • 2021-02-04 17:52

    I'm not sure if this would be the best way to go about it. The most obvious way to me, would be to make an HTTP Request, and call the webservice using an actual HTTP GET or POST. Using your method, I'm not entirely sure how you'd set up the data you are sending to the web service. I've added some sample code in 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()
    
    0 讨论(0)
  • 2021-02-04 17:52

    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.

    0 讨论(0)
  • 2021-02-04 17:53

    @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?

    0 讨论(0)
  • 2021-02-04 17:54

    @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.

    0 讨论(0)
提交回复
热议问题