2012-07-18 13 views
9

Tengo un servidor HTTP personalizado integrado en C# que acepta solicitudes de servicios REST y responde con XML o JSON (dependiendo de qué el cliente necesita). Los servicios REST se definen en el tiempo de ejecución a partir de una configuración basada en la base de datos, varían ampliamente en los parámetros de entrada y los tipos de salida, y está funcionando perfectamente en producción.Creando y exponiendo un servicio SOAP y su WSDL dinámicamente en C# (con un escucha TCP personalizado!)

Sin embargo, me gustaría agregar el acceso SOAP a los mismos servicios, con los WSDL apropiados también. Dado que los servicios disponibles no están codificados duro, esto significa:

  • Publicación de un WSDL generado en tiempo de ejecución a partir de las definiciones de métodos en la base de datos
  • análisis sintáctico peticiones SOAP entrantes, la cartografía de ellos a dichas definiciones, y asegurándose las solicitudes se ajustan a la firma del método antes de manipularlos
  • una vez que se maneja la respuesta, la creación de una reunión de respuesta SOAP del WSDL para devolver los resultados

la documentación de MS (y Google) documentos utilizando Visual Studio para generar web servi ces (y WSDL) en el momento del diseño, exponiendo cosas usando WebMethods, ASP.NET MVC, etc. Esto no es lo que estoy buscando, ya que no hay definiciones de métodos a partir de las cuales generar los enlaces en tiempo de diseño.

¿Alguien tiene alguna idea (por ejemplo, kits de herramientas para el análisis SOAP sin procesar) y pensamientos sobre la generación de WSDL a partir de firmas de métodos creados dinámicamente, etc.? ¿Alguna idea de cómo uno podría ir construyendo tales cosas si no? Estoy buscando evitar reinventar la rueda si es posible.

PD: Claramente hay material estandarizado en .NET Framework para esto, ya que Visual Studio lo hace por usted, ¿alguna idea de cómo acceder a eso en un nivel inferior, en tiempo de ejecución?

+1

_ "Los servicios REST se definen en tiempo de ejecución desde una configuración basada en base de datos" _ - Me estremecí cuando lo leí. ¿No es eso un infierno de mantenimiento y solución de problemas? – CodeCaster

+0

Estoy lidiando con una situación muy similar preguntándome si la respuesta aceptada funcionó para usted –

+0

np-hard - Hice una prueba de concepto e hizo lo que se pretendía. Sin embargo, no he distribuido nada a la producción, ya que en general pedirle a los clientes que implementen el servicio REST parecía una opción más confiable que el análisis manual, y cualquier error que pueda introducirse a través del complejo proceso de analizar manualmente las solicitudes SOAP. –

Respuesta

6

Para crear un WSDL dinámicamente puede utilizar ServiceDescriptionReflector

Por ejemplo: para la clase

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

puede utilizar este código

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(); 

Pero ya que has dicho

Publishin ga WSDL generado en tiempo de ejecución de las definiciones de métodos en la base de datos

usted tiene que crear el Type en tiempo de ejecución

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(); 

Ahora puede utilizar type para crear 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(); 

Para la lectura solicitud y formando respuesta, puede usar Linq2Xml. Fiddler puede darle una idea sobre el formato SOAP (xml) enviado entre el cliente y el servidor

+0

Eso es genial: ya he resuelto la creación del tipo, pero el ServiceDescriptionReflector era exactamente lo que estaba buscando. ¡Gracias! –

2

SOAP es "solo" un protocolo basado en XML para el intercambio de información. Implementar el apoyo para ello desde el principio sería tedioso, pero no muy complicado en principio, no creo.

Las especificaciones oficiales de SOAP se pueden encontrar here.

+0

Es sobre todo el tedio (y la posibilidad de errores) que quiero evitar, en lugar de esperar algún tipo de kit de herramientas para manejar el análisis SOAP. Sé que Microsoft tenía su Toolkit SOAP hace unos 10 años, pero fue desaprobado a favor de VS manejando todo ... ¡gracias, sin embargo! –

2

no analizar jabón a menos que realmente tiene que, por no WCF hacer el trabajo pesado para usted, generar servicio- y DataContracts en código C# de sus definiciones y compilar en tiempo de ejecución. Genere una implementación de servicio que enganche en su código "estático" a través de una interfaz bien conocida.

Cree dinámicamente puntos finales con el enlace correcto para los nuevos contratos de servicio/contratos de datos. Si los enlaces no cambian dinámicamente, esto podría definirse en su app.config; de lo contrario, establezca esto en tiempo de ejecución también.

agregue un punto final Mex para obtener el wsdl publicado.

para "examinar" el tráfico de entrada utilizar un auto MessageInspector

alojar el servicio WCF/SOAP en el servidor HTTP utilizando ServiceHost ->Self Hosting WCF

Sólo algunas ideas sobre otro enfoque.

+0

Posiblemente no sea lo suficientemente claro desde mi pregunta original, pero tanto los contratos de datos como los enlaces * do * cambian en tiempo de ejecución, por lo que no estoy usando WCF. Ese es el caso de uso aquí: un servidor que no pertenece a WCF/IIS y contratos que cambian (y con frecuencia también se crean) en tiempo de ejecución. –

+0

Si tanto los contratos como las consolidaciones cambian, ¿cómo utilizan sus clientes su servicio? ¿Debe ser difícil ubicar el servicio? –

+0

Obtuve el contrato dinámico y se soluciona generando dinámicamente los contratos, en cuanto al alojamiento, usted mismo podría alojar el servicio WCF/SOAP en su servidor HTTP utilizando ServiceHost http://msdn.microsoft.com/en-us/ library/ms730158.aspx. –

Cuestiones relacionadas