2009-05-30 15 views
7

Sto utilizzando una classe in un progetto ASP.NET C# per consentire uno script scritto in un linguaggio di script casuale per esporre dinamicamente i metodi di servizio web - in altre parole, lo script dovrebbe essere in grado di esporre un metodo di qualsiasi nome con qualsiasi firma (purché sia ​​valida, comunque) per il mondo esterno attraverso questa interfaccia SOAP (in grado di aggiungerli e rimuoverli a piacimento, senza bisogno di un cambiamento di codice), e come tale devo essere in grado di creare una classe webservice in C# pur essendo in grado di aggiungere e rimuovere dinamicamente i metodi in fase di runtime.Dynamic C# .NET Webservice

Ora, il piano migliore che ho potuto ottenere finora è (runtime) che genera codice C# per rappresentare il servizio web, utilizzando System.Reflection.Emit per compilarlo e quindi caricare l'assembly in fase di runtime - tutto ogni volta che lo script aggiunge o rimuove un metodo dal/al servizio (non dovrebbe accadere molto spesso, attenzione).

Qualcuno ha un'idea migliore di questa?

risposta

5

È possibile modificare WSDL utilizzando la classe SoapExtensionReflector. 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 per intercettare la chiamata di riflessione e modificare l'output 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); 
     } 
     } 
    } 
} 

Aggiungere questo alla configurazione sezione/system.web in web.config:

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

Questo dovrebbe darti un punto di partenza per la rimozione dinamica dei metodi dal documento WSDL. Avresti anche bisogno di lanciare NotImplementedException dal metodo web se è disabilitato.

Infine, è necessario disabilitare la documentazione del servizio Web prodotta richiamando .asmx endpoint senza? Parametro WSDL. Impostare l'attributo href dell'elemento wsdlHelpGenerator su un URL. È possibile utilizzare DefaultWsdlHelpGenerator.aspx come punto di partenza per il proprio gestore della documentazione. Vedere la domanda sulla documentazione del servizio Web in XML Files, August 2002.

1

Deve essere un'interfaccia SOAP? Sembra che potrebbe essere più adatto a una route/REST/ecc basata su API. Si potrebbe fare qualcosa in ASP.NET MVC (con un metodo personalizzato IController.Execute che risolve l'azione sul metodo) abbastanza facilmente (in effetti, sto lavorando a qualcosa di molto simile per some of my own code 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. In non-MVC dovresti essere in grado di fare qualcosa di simile con un gestore generico mappato con caratteri jolly.

+0

Grazie per la risposta rapida - sfortunatamente deve essere SAPONE. Stavo usando XMLRPC fino a questo punto, ma l'interfaccia con una terza parte che non vuole usare XMLRPC significa che devo contaminarlo con SOAP. :( –

+0

Hmm ... "buona fortuna con quello" ... –

2

XMLRPC è abbastanza morto, non è vero?

SOAP implica un WSDL. Come si genera il WSDL in modo dinamico?

Si dovrebbe esaminare utilizzando WCF. Mi aspetto che sarai in grado di assumere il controllo del processo di generazione del WSDL (e di altri metadati), ma dovresti anche essere in grado di assumere il controllo dell'elaborazione dei messaggi in arrivo. In particolare, sarà possibile esaminare i messaggi in arrivo per determinare quale script eseguire, quali parametri passare, ecc.

+0

Beh, per quanto posso dire che XMLRPC non è morto, non è nello stesso "mercato" di SOAP che penserei. XMLRPC è stato scelto per questo progetto perché richiedeva un'interfaccia semplice e dinamica che fosse facilmente leggibile/modificabile dall'uomo. Un sacco di sviluppo è stato fatto intorno a questo - quindi ora, sfortunatamente, abbiamo un progetto scritto usando XMLRPC e una terza parte testarda che si rifiuta di fare qualsiasi cosa non riesca a fare in modo che Visual Studio esegua il lavoro per loro. :( –

+0

Interessante. Per http://en.wikipedia.org/wiki/XML-RPC, mi è sempre sembrato che, dal momento che XML-RPC si è evoluto in sapone, era diventato un po 'di un "dinosauro". –

2

È possibile creare un servizio WCF con un tipo di input e output di xs:any e gestire la richiesta in ingresso come un grezzo Message. Ciò consentirebbe di accettare qualsiasi tipo di dati e restituire qualsiasi tipo di dati. Non useresti contratti dati o tipi statici, solo uno Message e uno Message.

Il problema con questo approccio è che la generazione di un proxy dal WSDL non fa realmente nulla per aiutare il consumatore se non fornire un wrapper per chiamare il metodo. Fornire dati accettabili per il metodo richiederebbe tipi di dati a rotazione manuale, ecc. Che non è così difficile, ma non è così intuitivo come un contratto duro, tipizzato.