2012-07-18 3 views
9

Ho un server HTTP personalizzato costruito in C# che accetta richieste per servizi REST e risponde con XML o JSON (a seconda di cosa il cliente ha bisogno). I servizi REST sono definiti in fase di esecuzione da una configurazione basata su database, variano ampiamente nei parametri di input e nei tipi di output e funzionano in modo ottimale durante la produzione.Creare ed esporre un servizio SOAP e il suo WSDL dinamicamente in C# (con un listener TCP personalizzato!)

Tuttavia, vorrei aggiungere l'accesso SOAP agli stessi servizi, anche con WSDL appropriati. Dal momento che i servizi disponibili non sono hard-coded, questo significa:

  • La pubblicazione di un WSDL generato in fase di esecuzione dalle definizioni di metodo nel database
  • Parsing richieste SOAP in arrivo, la mappatura di queste definizioni, e fare in modo le richieste sono conformi alla firma del metodo prima di maneggiare loro
  • una volta che la risposta viene gestita, creando un incontro risposta SOAP la WDSL per restituire i risultati

la documentazione MS (e Google) i documenti utilizzando Visual Studio per generare web Servi ces (e WSDL) in fase di progettazione, esponendo materiale tramite WebMethods, ASP.NET MVC ecc. Questo non è quello che sto cercando, in quanto non sono definizioni di metodo da cui generare i binding in fase di progettazione.

Qualcuno ha qualche idea (ad esempio toolkit per l'analisi SOAP non elaborata) e pensieri sulla generazione di WSDL da firme di metodo create in modo dinamico, ecc.? Qualche idea su come si possa andare a costruire cose del genere se no? Sto cercando di evitare di reinventare la ruota, se possibile.

PS: Chiaramente ci sono cose standardizzate nel framework .NET per questo, dal momento che Visual Studio lo fa per te - qualche idea su come accedervi a un livello più basso, in fase di runtime?

+1

_ "I servizi REST sono definiti in fase di runtime da una configurazione basata su database" _ - I brividi quando l'ho letto. Non è un inferno di manutenzione e risoluzione dei problemi? – CodeCaster

+0

Mi sto occupando di una situazione molto simile chiedendomi se la risposta accettata funzionasse per te –

+0

np-hard - Ho fatto una dimostrazione di concetto e ha fatto ciò che era inteso. Non ho mai esportato nulla in produzione, tuttavia, poiché il fatto di chiedere ai clienti di implementare il servizio REST sembrava una scelta più affidabile dell'analisi manuale e di eventuali bug che potrebbero essere introdotti attraverso il complesso processo di analisi manuale delle richieste SOAP. –

risposta

6

Per creare un WSDL in modo dinamico è possibile utilizzare ServiceDescriptionReflector

Ad esempio: per la classe

public class TestWebService 
{ 
    [WebMethod] 
    public string Hello(string namex) 
    { 
     return "Hello " + namex; 
    } 
} 

è possibile utilizzare questo codice

StringWriter wr = new StringWriter(); 
var r = new System.Web.Services.Description.ServiceDescriptionReflector(); 
r.Reflect(typeof(TestWebService), "http://somewhere.com"); 
r.ServiceDescriptions[0].Write(wr); 
var wsdl = wr.ToString(); 

Ma dal momento che hai detto

Publishin ga WSDL generato in fase di esecuzione dalle definizioni di metodo nel database

è necessario creare la Type in fase di esecuzione

var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("MyAsm"), AssemblyBuilderAccess.Run); 
var mod = asm.DefineDynamicModule("MyModule"); 

TypeBuilder typeBuilder = mod.DefineType("TestWebService"); 

MethodBuilder mb = typeBuilder.DefineMethod("Hello", MethodAttributes.Public, CallingConventions.Standard, typeof(string), new Type[] { typeof(string) }); 
var cab = new CustomAttributeBuilder(typeof(WebMethodAttribute).GetConstructor(new Type[]{}), new object[]{}); 
mb.SetCustomAttribute(cab); 
mb.DefineParameter(1, ParameterAttributes.In, "namex"); 
mb.GetILGenerator().Emit(OpCodes.Ret); 

Type type = typeBuilder.CreateType(); 

Ora è possibile utilizzare type per creare WSDL

StringWriter wr = new StringWriter(); 
var r = new System.Web.Services.Description.ServiceDescriptionReflector(); 
r.Reflect(type, "http://somewhere.com"); 
r.ServiceDescriptions[0].Write(wr); 
var wsdl = wr.ToString(); 

Per la lettura richiesta e formando una risposta, è possibile utilizzare Linq2Xml. Fiddler può darti un'idea del formato SOAP (xml) inviato tra client e server

+0

È fantastico: ho già risolto la creazione del tipo, ma ServiceDescriptionReflector era esattamente quello che stavo cercando. Grazie! –

2

SOAP è "solo" un protocollo basato su XML per lo scambio di informazioni. Implementare il supporto per questo da zero sarebbe noioso, ma non molto complicato in linea di principio, non credo.

Le specifiche SOAP ufficiali sono disponibili here.

+0

È principalmente la noia (e il potenziale per i bug) che sto cercando di evitare - piuttosto sperando in qualche tipo di toolkit per la gestione del parsing SOAP ecc. So che Microsoft aveva il loro SOAP Toolkit circa 10 anni fa, ma era deprecato a favore di VS gestisce tutto ... grazie, però! –

2

non analizzano SOAP se non si ha veramente, lasciare che WCF fare il lavoro pesante per voi, generare servizio- e datacontracts in codice C# dalle vostre definizioni compilare in fase di esecuzione. Genera un'implementazione del servizio che si aggancia al tuo codice "statico" tramite un'interfaccia ben nota.

Creare dinamicamente gli endpoint con l'associazione corretta per i nuovi contratti di servizio/contratti di dati. Se i collegamenti non cambiano dinamicamente, ciò potrebbe essere definito in app.config, altrimenti lo si può impostare anche in runtime.

aggiungere un endpoint Mex per ottenere la wsdl pubblicata.

per "esaminare" il traffico in entrata utilizzare un MessageInspector

sé ospitare il/servizio SOAP WCF nel vostro server HTTP usando ServiceHost ->Self Hosting WCF

Solo alcune idee su un altro approccio.

+0

Forse non è abbastanza chiaro dalla mia domanda originale, ma sia i contratti dati che i collegamenti * fanno * cambiano in fase di esecuzione, motivo per cui non sto usando WCF. Questo è il caso d'uso qui - un server non WCF/IIS e contratti che cambiano (e sono spesso creati anche) in fase di runtime. –

+0

Se i contratti e le associazioni cambiano in che modo i clienti utilizzano il servizio? Deve essere difficile individuare il servizio? –

+0

Ho ottenuto il bit del contratto dinamico e viene indirizzato generando dinamicamente i contratti, in quanto per l'hosting è possibile ospitare autonomamente il servizio WCF/SOAP nel server HTTP utilizzando ServiceHost http://msdn.microsoft.com/en-us/ libreria/ms730158.aspx. –