viernes, 15 de febrero de 2008

WCF - Creando un nuevo Behavior

Continuo con VS2008, con WCF (Windows Communication Foundation), en este caso integrando WCF con JAVA y más concretamente con una aplicación desarrollada en AXIS 1.1.0.xxx, vamos, "una patata" un problema, puesto que es la primera y obsoleta versión, no cumple muchos puntos del estandard WSDL, el principal  es que no permite las cláusulas <import>, es decir, es necesario generar un WSDL "to junto", en fin, cosas del directo como se suele decir, jeje...

Para conocer como afrontar este inconveniente, os cuento lo que he hecho:

Se trata de crear una extensión para nuestro WCF y en cierta forma dotarlo de una nueva funcionalidad, para ello usaremos los interfaces; IWsdlExportExtension, IEndpointBehavior. Entrando más en detalle, necesitaremos añadir código al evento ExportEndPoint de IWsdlExportExtension tal y como muestro a continuación:

public void ExportEndpoint(
WsdlExporter exporter,
WsdlEndpointConversionContext context
)
{
XmlSchemaSet schemaSet
= exporter.GeneratedXmlSchemas;
foreach (WsdlDescription wsdl in exporter.GeneratedWsdlDocuments)
{
List
<XmlSchema> importsList = new List<XmlSchema>();
foreach (XmlSchema schema in wsdl.Types.Schemas)
{
AddImportedSchemas(schema, schemaSet, importsList);
}
wsdl.Types.Schemas.Clear();
foreach (XmlSchema schema in importsList)
{
RemoveXsdImports(schema);
wsdl.Types.Schemas.Add(schema);
}
}
}

private void AddImportedSchemas(
XmlSchema schema,
XmlSchemaSet schemaSet,
List
<XmlSchema> importsList
)
{
foreach (XmlSchemaImport import in schema.Includes)
{
ICollection realSchemas
=
schemaSet.Schemas(import.Namespace);
foreach (XmlSchema ixsd in realSchemas)
{
if (!importsList.Contains(ixsd))
{
importsList.Add(ixsd);
AddImportedSchemas(ixsd, schemaSet, importsList);
}
}
}
}

private void RemoveXsdImports(XmlSchema schema)
{
for (int i = 0; i < schema.Includes.Count; i++)
{
if (schema.Includes[i] is XmlSchemaImport)
schema.Includes.RemoveAt(i
--);
}
}


El resto de métodos a sobrescribir podrán dejarse vacíos.


Adicionalmente y para poder configurar nuestro WCF con la herramienta de configuración (WCF Service Configuration Editor), será necesario:


public class InlineXsdBehaviorSection : BehaviorExtensionElement
{

protected override object CreateBehavior()
{
return new InlineXsdInWsdlBehavior();
}

public override Type BehaviorType
{
get
{
Type t
= Type.GetType("MyProject.WCF.Extensions.InlineXsdInWsdlBehavior");
return t;
}
}
}

Finalmente tendremos que incluir esta DLL en el GAC, creando previamente un Strong Key, o bien, incluir la referencia en nuestro proyecto, con "Copy Local = true". Al menos durante el desarrollo os recomiendo que la incluyais en el GAC, evitará el estar constantemente seleccionando esta dll cada vez que editamos la configuración con el "WCF Service Configuration Editor", "menuda lata, ¿no?".


Para poner en marcha nuestro WCF:







Si ahora comprobamos el WSDL de nuestro WCF veremos como ya no incluye ninguna clausula "import".


Esto no es del todo cierto, jejeje... existe un inconveniente/restricción y dependerá de los Namespaces de nuestras clases, es decir, será necesario que todos los Namespaces sean iguales, vamos, que sólo exista un único Namespace.  Para ver como cambiar el namespace,  echad un vistazo a este otro post; "tempuri.org con WCF".


 


Para mayor detalle y comprensión sobre los behaviors, os sugiero que le echéis un vistazo a un artículo de la MSDN Magazine de Diciembre de 2007:   http://msdn.microsoft.com/msdnmag/issues/07/12/ServiceStation/default.aspx?loc=es

 

Nota: Para el siguiente post contaré sobre "ASP NET Compatibility" y lo que ofrece sobre todo a aquellos que estamos empezando con WCF.

 

Saludos y suerte en vuestras nuevas extensiones
Juanlu


lunes, 11 de febrero de 2008

Evitando el namespace "http://tempuri.org" con WCF

Hace unos días me toco quitar el ya conocido http://tempuri.org del WSDL y asignarle un namespace específico, es más, esto es lo recomendado por seguridad y como buena practica, en fin, para conseguirlo bastará con lo siguiente:

[ServiceContract(Namespace = "http://MyProject.Tests")]






[DataContract(Namespace="http://MyProject.Tests")]





1 <service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior">
2 <endpoint bindingNamespace="http://MyProject.Tests" address="" binding="wsHttpBinding" contract="WcfService1.IService1">


ó, graficamente:




El valor para esta propiedad, aunque puede ser cualquiera, ¡con un poco de sentido común, claro!, sería conveniente que tomara el mismo que el indicado para el "[ServiceBehavior]".



Este último punto fue el que más tardé en encontrar, ¡y mira que está visible! :-D  ¡si leyera un poco de vez en cuando!, jeje... ¡si es que lo dice claramente al pie de la ventana! De todos modos, es curioso, porque todos los post y artículos que hacen referencia a los namespaces, pasan por alto este último punto.


 


Una ayudita más, un gran logro, :-D.


Saludos
Juanlu

Etiquetas: , , ,


This page is powered by Blogger. Isn't yours?