Question

Disons que j’ai un service Web ASMX, MyService. Le service a une méthode, MyMethod. Je pourrais exécuter MyMethod côté serveur comme suit:

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

Je dois faire la même chose, avec un service et une méthode inconnus jusqu'au moment de l'exécution.

Je suppose que cette réflexion est la meilleure façon de s'y prendre. Malheureusement, j'ai du mal à le faire fonctionner. Quand j'exécute ce code:

Type.GetType("MyService", true);

Il lève cette erreur:

  

Impossible de charger le type 'MyService' de l'assembly 'App_Web__ktsp_r0, version = 0.0.0.0, Culture = neutre, PublicKeyToken = null'.

Toute orientation serait appréciée.

Était-ce utile?

La solution

Je ne sais pas si ce serait la meilleure façon de s'y prendre. Le moyen le plus évident pour moi serait de faire une requête HTTP et d’appeler le service Web à l’aide d’un HTTP GET ou POST réel. Avec votre méthode, je ne sais pas trop comment vous allez configurer les données que vous envoyez au service Web. J'ai ajouté des exemples de code dans 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()

Autres conseils

// Essayez ceci - >

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

Bien que je ne sache pas pourquoi Reflection ne fonctionne pas pour vous ici (je suppose que le compilateur pourrait créer une nouvelle classe à partir de vos annotations [WebService] ), voici quelques conseils qui pourraient résoudre votre problème:

Conservez votre WebService simple, superficiel, bref: implémentation du motif de façade .

Faites en sorte que le calcul de votre délégation de service soit effectué dans une classe d'implémentation, qui devrait facilement pouvoir être appelée via Reflection. Ainsi, votre classe WebService n’est qu’un front pour votre système. Vous pouvez même ajouter un gestionnaire de messagerie, une interface XML-RPC, etc., puisque votre logique n’est pas couplée au WebService, mais à un véritable objet de la couche de gestion.

Pensez aux classes WebService en tant qu'objets de couche d'interface utilisateur dans votre architecture.

Voici une réponse rapide que quelqu'un peut probablement développer.

Lorsque vous utilisez l'application de modèle WSDL (WSDL.exe) pour générer des wrappers de service, il crée une classe de type SoapHttpClientProtocol. Vous pouvez également le faire manuellement:

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

Je n'ai pas testé ce code mais j'imagine qu'il devrait fonctionner de manière autonome sans avoir à exécuter l'outil WSDL.

Le code que j'ai fourni est le code de l'appelant qui se connecte au service Web via un appel distant (même si, pour une raison quelconque, vous ne voulez pas qu'il soit distant.) La méthode Invoke prend en charge le conditionnement comme un appel de savon. Le code de @Dave Ward est correct si vous souhaitez ignorer l'appel du service Web via HTTP, à condition que vous puissiez réellement référencer la classe. Peut-être que le type interne n’est pas "MyService". - vous devez vérifier le code du contrôle pour en être sûr.

@Kibbee: Je dois éviter les pertes de performances HTTP. Ce ne sera pas un appel distant, de sorte que toute la surcharge ajoutée ne devrait pas être inutile.

@ Daren: Je suis tout à fait d'accord avec cette philosophie de conception. Le problème ici est que je ne vais pas contrôler le service ou sa logique métier sous-jacente.

Il s’agit du d'un contrôle de serveur devant être exécuté sur un service / une méthode arbitraire, orthogonalement à la manière le service Web lui-même est implémenté.

Bien que je ne puisse pas dire dans votre message:

Une chose à garder à l'esprit est que si vous utilisez la réflexion, vous devez créer une instance de la classe de service Web générée automatiquement (celle créée à partir du WSDL de votre service Web). Ne créez pas la classe responsbile pour le côté serveur du service.

Donc, si vous avez un service Web

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

vous ne pouvez pas référencer cet assembly dans votre client et faire quelque chose comme:

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

@Radu: Je suis capable de créer une instance et d'appeler la méthode exactement comme ça. Par exemple, si j’ai cet 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";
  }
}

Je peux l'appeler à partir du code ci-dessous d'une page ASPX:

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

Voulez-vous dire que cela ne devrait pas fonctionner?

J'ai réfléchi à cette question et je pense que vous êtes confronté au fait que le code ASMX sera intégré à une DLL portant un nom aléatoire dans le cadre de la compilation dynamique de votre site. Votre code pour rechercher le type recherchera, par défaut, uniquement son propre assemblage (une autre DLL App_Code, à l'apparence de l'erreur que vous avez reçue) et ses bibliothèques principales. Vous pouvez fournir une référence d'assemblage spécifique " TypeName, AssemblyName " GetType (), mais cela n’est pas possible dans le cas des assemblys générés automatiquement, qui portent de nouveaux noms après chaque recompilation.

Solution .... Je ne l'ai pas fait moi-même auparavant, mais je pense que vous devriez pouvoir utiliser quelque chose comme ceci:

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

en tant que BuildManager est conscient des DLL qu'il a créées et sait où chercher.

Je suppose que cela n'a pas vraiment à voir avec les services Web, mais s'il s'agissait de votre propre code, Daren a raison en ce qui concerne les modèles de façade.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top