Obtener datos de Salesforce Usando el API REST desde un Servicio Web en .Net
En un artículo anterior, Un Servicio WCF en .Net Procesando Mensajes Salientes de Flujo de Trabajo de Salesforce y con Llamadas a Salesforce usando el API SOAP, explique cómo crear un servicio WCF en .Net para procesar mensajes salientes y obtener información adicional de Salesforce. En este artículo usaré el mismo ejemplo pero en cambio de usar el API SOAP usaré el API REST. Te puedes estar preguntando por que necesito cambiar mi código en SOAP y usar REST, y la respuesta es sencilla: es posible que tengas el API SOAP deshabilitado (debido a la edición de Salesforce que tienes) en tu organización y solo tener disponible el API REST.
Permitidme refrescar lo que queremos realizar: nuestro cliente quiere integrar las cuentas de Salesforce con las cuentas del ERP, por lo que, cada vez que una nueva oportunidad es ganada y pasada a la etapa “Closed Won” en Salesforce, la cuenta es creada en el ERP. Te sugiero que leas el artículo anterior donde se explica cómo configurar el flujo de trabajo en Salesforce y la creación del Proyecto de Visual Studio para crear el servicio WCF para procesar los mensajes salientes del flujo de trabajo.
Salesforce permite exponer la metadata como un servicio REST. Tal y como hicimos en el caso de SOAP, podríamos usar el API REST para consultar la información de cuentas, pero esto puede simplificarse bastante exponiendo una clase APEX como un servicio REST. Salesforce hace que esto sea bien sencillo. Puedes seguir los pasos explicados en la guía Force.com Apex Code Developer’s Guide para ver un ejemplo de cómo hacerlo. En este artículo vamos a exponer una clase APEX como un servicio REST y luego consumir este servicio desde un procesador de mensajes salientes de flujo de trabajo en .Net.
Creación del Servicio REST en Salesforce
Esto es en realidad bastante sencillo, todo lo que hay que hacer es abrir la Consola de Desarrollo y desde el menú seleccionar “File->New->Apex Class”. Llama la clase AccountRestService y reemplaza el código con lo siguiente:
@RestResource(urlMapping='/Account/*') global with sharing class AccountRestService { @HttpGet global static Account doGet() { RestRequest req = RestContext.request; RestResponse res = RestContext.response; String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1); Account result = [SELECT Id, Name, BillingStreet, BillingCity, BillingState, BillingPostalCode FROM Account WHERE Id = :accountId]; return result; } }
Nota en la línea 1 que hemos usado el atributo @RestResource para indicarle a Salesforce que esto es un servicio REST. En la línea 3 especificamos que el método doGet será llamado mediante HTTP GET. El URL para este servicio será el siguiente:
La parte de https://{instanceName}.salesforce.com/services/apexrest es el URL base para todos los servicio REST de la organización, y la parte /Account/{accountId} es la parte especificada en la definición de la clase en el parámetro urlMapping del atributo @RestResource. Por ejemplo, el siguiente URL to retornaría los detalles específicos de una cuenta:
Hay algo que todavía no hemos considerado: la seguridad. Si colocas el URL anterior en un navegador vas a ver el error INVALID_SESSION_ID. Si leemos la documentación veremos que la solicitud del servicio REST requiere el encabezado de HTTP de Authorization. Es posible crear una aplicación conectada y usar OAut para llamar al servicio REST de autenticación y así obtener el id de sesión, pero esto es algo complejo (lo explicaré en un artículo más adelante), y en nuestro caso, debido a que vamos a realizar la llamada de este servicio desde un procesador de mensajes salientes de flujo de trabajo, ya tenemos el id de sesión. Recuerda del artículo anterior que hemos marcado en el mensaje saliente la opción de “Enviar Id. de sesión”:
Así que todo lo que hay que hacer es construir la solicitud HTTP desde el servicio WCF y llamar al servicio REST.
Llamar al Servicio REST desde Visual Studio
Abre el proyecto de Visual Studio creado en el artículo anterior (puedes obtener el proyecto de ejemplo desde aquí). Vamos a usar RestSharp como cliente REST para llamar al servicio. Mediante NuGet, agrega el paquete RestSharp al proyecto. RestSharp puede convertir automáticamente el texto JSON retornado por un servicio REST a un objeto fuertemente tipado. Vamos a crear un modelo para encapsular los datos retornados por el servicio REST: en Visual Studio, crea un directorio llamado Model y agrega una nueva clase llamada Account. Reemplaza el código con lo siguiente:
namespace WorkflowNotificationServices.Model { public class Account { public string Id { get; set; } public string Name { get; set; } public string AccountNumber { get; set; } public string BillingStreet { get; set; } public string BillingCity { get; set; } public string BillingState { get; set; } public string BillingPostalCode { get; set; } public string BillingCountry { get; set; } } }
Hemos definido un objeto para encapsular los datos del objeto cuenta en Salesforce. Nótese que para simplificar las cosas hemos llamado las propiedades de la clase de igual forma que los nombres de los campos del objeto en Salesforce (no es necesario que los nombres coincidan, se podría usar JSON.Net para tener nombres diferentes, pero en este artículo no lo haremos para no complicar las cosas).
A continuación, abre el archivo OpportunityNotificationService.svc.cs y cambia el método CreateAccount con el código siguiente:
private bool CreateAccount(string url, string sessionId, WorkflowNotificationServices.Opportunity opportunity) { int recordsAffected = 0; Uri uri = new Uri(url); RestClient restClient = new RestClient(new Uri(String.Format("https://{0}", uri.Host))); RestRequest request = new RestRequest("services/apexrest/Account/{id}"); request.AddUrlSegment("id", opportunity.AccountId); request.AddHeader("Authorization", String.Format("Bearer {0}", sessionId)); IRestResponse<Model.Account> response = restClient.Execute<Model.Account>(request); Model.Account account = response.Data; ConnectionStringSettings connectionString = ConfigurationManager.ConnectionStrings["ERP"]; using (SqlConnection cn = new SqlConnection(connectionString.ConnectionString)) { using (SqlCommand command = new SqlCommand("salesforce_crearCliente", cn)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.Add("@idSalesforce", SqlDbType.VarChar).Value = account.Id; command.Parameters.Add("@name", SqlDbType.VarChar).Value = account.Name; command.Parameters.Add("@number", SqlDbType.VarChar).Value = (object)account.AccountNumber ?? DBNull.Value; command.Parameters.Add("@address", SqlDbType.VarChar).Value = (object)account.BillingStreet ?? DBNull.Value; command.Parameters.Add("@city", SqlDbType.VarChar).Value = (object)account.BillingCity ?? DBNull.Value; command.Parameters.Add("@state", SqlDbType.VarChar).Value = (object)account.BillingState ?? DBNull.Value; command.Parameters.Add("@postalCode", SqlDbType.VarChar).Value = (object)account.BillingPostalCode ?? DBNull.Value; command.Parameters.Add("@country", SqlDbType.VarChar).Value = (object)account.BillingCountry ?? DBNull.Value; cn.Open(); recordsAffected = command.ExecuteNonQuery(); } } return recordsAffected > 0; }
Las líneas resaltadas son las más importantes. En la línea 6 usamos el URL que obtuvimos del mensaje SOAP enviado por Salesforce a nuestro servicio WCF, de donde obtenemos el servidor (y de aquí el nombre de la instancia) al cual debemos enviar las solicites HTTP. En la línea 7 se crea la solicitud HTTP usando RestSharp y se especifica el URL de nuestro servicio REST, tal y como se explicó anteriormente. En la línea 8 se especifica el Id de la cuenta que obtenemos del mensaje saliente de la oportunidad. En la línea 9 especificamos los parámetros de seguridad para que la llamada funcione. Necesitamos fijar el encabezado Authorization con el valor Bearer {sessionId}. El id de sesión lo obtenemos nuevamente del mensaje saliente enviado por Salesforce (recuerda que marcamos el parámetro “Enviar Id. de sesión” en la creación del mensaje saliente en Salesforce). Finalmente, en la línea 12 realizamos la llamada HTTP y le pedimos a RestSharp que el resultado (texto JSON) lo convierta al objeto Account creado anteriormente. El resto del código es básicamente el mismo, usamos los valores retornados por el servicio REST (ahora contenidos en un objeto fuertemente tipado) para llamar un procedimiento almacenado en el ERP.
Probando la Llamada
Para probar nuestro servicio web solo tenemos que seguir los mismos pasos indicados en el artículo anterior. Solamente hemos cambiado el API que usamos para obtener datos de Salesforce: antes usábamos SOAP y ahora usamos REST.
La versión original de este articulo ha sido publicada en http://www.giovannimodica.com/
Grupo Lanka es partner certificado para Salesforce España.