lunes, 28 de junio de 2010

Parámetros de cualquier tipo en métodos de RIA services

Bueno, pues resulta que estaba yo tan feliz y contento escribiendo unos métodos para un servicio RIA, cuando me he encontrado con un problemilla inesperado. Digamos que yo había implementado un método tal que este:

En el cliente, el método debe ser invocado así:

donde ItemsFilter es una clase que contiene un puñado de criterios de filtrado para los datos que deben ser devueltos. Todo muy bonito y rebosante de felicidad.

Peeeero... resulta que tal código no compila. Da un error como este: Operation named 'GetItems' does not conform to the required signature. Parameter types must be an entity type or one of the predefined serializable types.

¿Y dónde está el problema? Pues en este foro de MSDN, donde la gente se caga en muestra un profundo malestar con el equipo de desarrollo de Microsoft, está explicado ferpectamente: No se pueden pasar tipos arbitrarios como parámetros a los métodos de un servicio RIA, sólo unos cuantos tipos predefinidos (mayormente, cadenas y números).

Por suerte, esto tiene una solución más o menos sencilla: se trata de cambiar el parámetro conflictivo para que sea una cadena en vez de ser del tipo deseado. En el cliente se serializa en XML el objeto en cuestión, en el servidor se deserializa, y todos contentos. Esto funcionará si la clase del parámetro se puede serializar en XML, cosa que para objetos sencillos de transferencia de datos normalmente será cierta.

¿Y cómo conseguimos tal cosa? Pues si quieres saber cómo lo he hecho yo, sigue leyendo.

En primer lugar he creado en el proyecto de servidor una clase auxiliar con métodos estáticos para serializar y deserializar objetos en XML. He llamado al fichero SerializationHelper.shared.cs, de esta forma lo tengo disponible también en el cliente. Este es el código de la clase:

A continuación he modificado el código del método en el servicio para que admita una cadena como parámetro, a partir de la cual se reconstruye el objeto:

Y en cuanto al cliente, el código de invocación es ahora este:

...y con este un tanto incómodo pero útil truquillo, ya podemos seguir RIAcizando felices y contentos. La pregunta es: ¿por qué no hace esto ya el compilador? ¿Qué llevó a los diseñadores del entorno RIA a imponer una limitación tan tonta? Misterio misterioso.

1 puesyocreoques:

Samuel Boings dijo...

Hola, lidiando con algo similar a esto debo ejecutar un SP que necesita 2 parámetros, el problema es que no puedo llamarlo en el cliente. Mi servicio se llama DomainService1 y lo instancio creando un objeto o incluso con DomainContext pero en las opciones no tengo acceso al SP que se llama DatosGrafica1, éste está definido así:


public IQueryable DatosGrafica1(string inicioperiodo, string finalperiodo)
{
return this.ObjectContext.SC1Grafica1(inicioperiodo,finalperiodo).AsQueryable();

}
¿Alguna sugerencia?