miércoles, 15 de diciembre de 2010

Consumir servicios externos desde código SandBoxed

El título de este post puede llevarnos a pensar que voy a hablar de Office365, sobretodo por el concepto SandBox y por el requerimiento de llamar a un servicio externo desde mi SharePoint en la nube. La verdad es que me gustaría que fuera así, pero todavía no es momento de hablar de la nueva versión de BPOS y de lo que ofrecerá cuando la primera beta se haga pública. No obstante, os puedo hablar de CRM 2011, del cual hoy me he enterado que ya tenemos disponible la RC, y se da el caso que también utiliza el concepto SandBox cuando se habla de despliegue de soluciones personalizadas sobre la versión online del producto. Obviamente, la necesidad de consumir servicios externos desde esta plataforma será también un requerimiento más que común. Se nos pueden dar varias opciones, desde tener que consumir un servicio “privado” que interactúe con un sistema interno dentro de nuestra infraestructura o la de un tercero a tener que consumir un servicio “público” proporcionado por cualquier organización. Vayamos por partes…

Si tenemos que consumir un servicio privado las opciones se minimizan y todo apunta a que tenemos que utilizar AppFabric y, más en concreto, el Service Bus. Si tenemos que consumir un servicio público el abanico de posibilidades se abre, almenos en teoría. En este post os voy a explicar un ejemplo concreto de este caso. Imaginemos que tenemos que desarrollar un servicio para publicarlo en Azure y que queremos consumir desde CRM 2011 Online. Evidentemente podemos seguir usando AppFabric para este caso pero, siendo nuestras las dos piezas y estando ambas alojadas en la nube, ¿no puedo hacerlo por mis propios medios? La respuesta no es evidente, y si empezas a hacer tus pruebas te vas encontrando con algunas limitaciones de la tecnología. Entonces, ¿cómo lo hago? la respuesta es REST. A continuación os detallo los pasos que deberíais seguir para montar una solución similar.

Lo primero, añadir una referencia (si no la teníais ya) a los ensamblados System.ServiceModel y System.ServiceModel.Web. A continuación, incluir un servicio WCF dentro de nuestro sitio web que queremos publicar en Azure. Esta acción crea tres ficheros en nuestro proyecto. Primero editamos el archivo Service1.svc y añadimos el atributo Factory="System.ServiceModel.Activation.WebServiceHostFactory" dentro del nodo ServiceHost. El fichero resultante quedará así:

<%@ ServiceHost Language="C#" Debug="true"
    Service="WebApplication1.Service1"
    CodeBehind="Service1.svc.cs"
    Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Después editamos el fichero IService1.cs que es la interfaz del servicio WCF para añadir la firma del método o de los métodos que queremos publicar. En este caso, expongo un método llamado GetIntegerResult que devolverá un valor entero.

namespace WebApplication1
{
    using System.ServiceModel;
    using System.ServiceModel.Web;
 
    [ServiceContract]
    public interface IService1
    {
        [OperationContract(Name = "GetIntegerResult")]
        [WebInvoke(UriTemplate = "/", Method = "GET")]
        int GetIntegerResult();
    }
}

Una vez hecho esto tenemos que añadir la implementación del método que devuelve dicho valor entero. Para ello, editamos el fichero Service1.svc.cs y escribimos lo siguiente:

namespace WebApplication1
{
    public class Service1 : IService1
    {
        public int GetIntegerResult()
        {
            return 3;
        }
    }
}

Si compilamos este código y accedemos vía web a nuestro servicio usando la url http://localhost:49254/Service1.svc/ (donde localhost:49254 es la url principal de vuestra aplicación web) observaréis un resultado como el de la figura:

image

El ejemplo, como se puede apreciar es muy simple y estoy pasando por alto muchas consideraciones pero el resumen es que si yo hago un GET de esta url obtengo el resultado que observáis en la figura. Ahora, ¿cómo hago ese GET? Está claro que hay múltiples respuestas para esta pregunta pero lo que parece evidente es que no vamos a tener muchas trabas tecnológicas independientemente de la tecnología que utilicemos siempre y cuando el servicio al que quiero llamar sea visible desde el sistema que estoy extendiendo, ya sea CRM 2011 Online, Office 365 o X. Para que sea visible deberemos publicar nuestro servicio en azure. Vamos a suponer que he publicado mi aplicación web en http://myapp.cloudapp.net y que, por lo tanto, si en mi navegador pongo http://myapp.cloudapp.net/Service1.svc veré una figura exactamente igual que la anterior. Para realizar la llamada desde C# una posibilidad es la siguiente:

Añadimos referencias a los ensamblados Microsoft.Http y Microsoft.Http.Extensions. Estos ensamblados los podréis encontrar dentro del WCF REST Starter Kit. A continuación, desde el sitio desde el cual quieras llamar a tu servicio, introduce el siguiente código.

string uri = "http://myapp.cloudapp.net/Service1.svc/";
using (HttpResponseMessage response = new HttpClient().Get(uri))
{
    // TODO: tratar la respuesta aquí    
    // No olvidéis la siguiente línea al principio del fichero:
    //    using Microsoft.Http;
}

Así de simple, independientemente de la tecnología que uses […] Bueno en realidad siempre hay una trampa, o varias. Si recordáis el título del artículo hablaba sobre CRM 2011 Online y yo sólo os he dado el punto de partida, la primera pista. .NET puro y duro que deberéis saber cómo publicar en CRM 2011 Online, en Office 365 o donde buenamente queráis. La segunda pista en la cadena CRM 2011 Online – SandBox – REST es Plugin.

Aún a riesgo de que me odiéis por haber metido sólo la puntita dejaros con la miel en los labios, voy a dejar el artículo aquí por el momento con la promesa de escribir una continuación digna a lo largo de esta semana.

 

Actualizado a lo largo de esa semana…

Os dejo aquí la segunda parte de este artículo.

0 comentarios: