Domanda

Sto utilizzando una classe in un progetto C # ASP.NET per consentire uno script scritto in qualche linguaggio di scripting casuale per esporre metodi webservice dinamico - in altre parole, lo script dovrebbe essere in grado di esporre un metodo di qualsiasi nome con ogni firma (a patto che sia valida, in ogni caso) con il mondo esterno tramite questa interfaccia SOAP (in grado di aggiungere e rimuovere a proprio piacimento, senza bisogno di un cambiamento di codice duro), e come tale ho bisogno di essere in grado di creare una classe webservice in C # pur essendo in grado di aggiungere in modo dinamico e rimuovere i metodi in fase di esecuzione.

Ora, il miglior piano che ho potuto venire con finora è (runtime) la generazione di codice C # per rappresentare il webservice, utilizzando System.Reflection.Emit compilarlo e poi caricare il gruppo in fase di esecuzione - tutto ogni volta lo script aggiunge o rimuove un metodo per / dal servizio (non dovrebbe accadere molto spesso, la mente).

Qualcuno ha un'idea migliore di questo?

È stato utile?

Soluzione

È possibile modificare WSDL utilizzando SoapExtensionReflector di classe. Da Kirk Evans Blog :

  

Il SoapExtensionReflector viene chiamato quando il tipo viene riflessa verso fornire la definizione WSDL per il vostro servizio. È possibile sfruttare questo tipo di intercettare la chiamata di riflessione e modificare l'uscita WSDL.

L'esempio seguente rimuove il primo metodo di metodi di servizio 2 web:

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

   [WebMethod]
   public int Multiply(int a, int b)
   {
      return a * b;
   }
}

Creare una classe ereditata da SoapExtensionReflector:

namespace TestWebservice
{
   public class MyReflector : SoapExtensionReflector
   {
      public override void ReflectMethod()
      {
         //no-op
      }

      public override void ReflectDescription()
      {
         ServiceDescription description = ReflectionContext.ServiceDescription;
         if (description.PortTypes[0].Operations.Count == 2)
            description.PortTypes[0].Operations.RemoveAt(0);
         if (description.Messages.Count == 4)
         {
            description.Messages.RemoveAt(0);
            description.Messages.RemoveAt(0);
         }
         foreach (Binding binding in description.Bindings)
         {
            if (binding.Operations.Count == 2)
               binding.Operations.RemoveAt(0);
         }
         if (description.Types.Schemas[0].Items.Count == 4)
         {
            description.Types.Schemas[0].Items.RemoveAt(0);
            description.Types.Schemas[0].Items.RemoveAt(0);
         }
      }
   }
}

Aggiungi questo alla sezione di configurazione / system.web nel web.config:

<webServices>
   <soapExtensionReflectorTypes>
      <add type="TestWebservice.MyReflector, TestWebservice" />
   </soapExtensionReflectorTypes>
</webServices>

Questo dovrebbe dare un punto di partenza per rimuovere in modo dinamico i metodi da un documento WSDL. Si sarebbe anche bisogno di gettare NotImplementedException dal metodo Web se è disattivato.

Infine, è necessario disabilitare la documentazione servizio web prodotta da invocando .asmx endpoint senza? Parametro WSDL. Impostare l'attributo href dell'elemento wsdlHelpGenerator ad alcuni URL. È possibile utilizzare DefaultWsdlHelpGenerator.aspx come punto di partenza per il proprio gestore di documentazione. Vedere domanda sulla documentazione servizio web in Files, agosto 2002 .

Altri suggerimenti

XMLRPC è abbastanza morto, non è vero?

SOAP implica un WSDL. Come si fa a generare il WSDL dinamicamente?

Si dovrebbe considerare di usare WCF. Mi aspetto che sarete in grado di prendere il controllo del processo di generazione WSDL (e altri metadati), ma si dovrebbe anche essere in grado di prendere il controllo del trattamento dei messaggi in arrivo. In particolare, si sarà in grado di esaminare i messaggi in arrivo per determinare quale l'esecuzione di script, quali parametri di passare, ecc.

Si può creare un servizio WCF con un tipo di input e l'output di xs:any e gestire la richiesta in ingresso come Message grezzo. Ciò consentirebbe di accettare qualsiasi tipo di dati e restituire qualsiasi tipo di dati. Tu non utilizzare contratti dati o tipi statici, solo un Message dentro e un fuori Message.

Il problema di questo approccio è che la generazione di un proxy dal WSDL fa davvero nulla per aiutare il consumatore diverso da fornire un wrapper per chiamare il metodo. Il conferimento dei dati che sia accettabile per il metodo richiederebbe tipi di dati hand-rolling, ecc che non è così difficile, non solo è intuitivo come un duro, digitato contratto.

Essa non deve essere un interfaccia SOAP? Che suona come potrebbe essere più adatto a un / etc API basata percorso / REST. Si potrebbe fare qualcosa in ASP.NET MVC (con un metodo personalizzato IController.Execute che risolve l'azione al metodo) abbastanza facilmente (in realtà, sto lavorando su qualcosa di molto simile per alcuni dei miei codice al momento).

Ad esempio, si potrebbe avere percorsi:

http://myserver/myservice/mymethod

che accetta (sia nel corpo o args) il carico utile (parametri), e restituisce il risultato nella risposta. Nel settore non-MVC si dovrebbe essere in grado di fare qualcosa di simile con un gestore generica jolly-mapped.

Ecco un suggerimento:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top