c# wcf salesforce

c# - Contract-First WCF para mensajería saliente de Salesforce



(5)

Descubrí una manera fácil de generar interfaces WCF desde el WSDL de Salesforce usando las herramientas integradas de Visual Studio. Descargué el WSDL de Salesforce y lo guardé en mi escritorio. En Visual Studio, ve al menú Agregar referencia de servicio en uno de tus proyectos (no importa dónde, vas a eliminar esto). Para la URL, ingrese la ruta al WSDL que descargó localmente (es decir, C: / Users / su nombre de usuario / Escritorio / notification.wsdl)

Esto debería traer carga en los datos para el servicio. Haga clic en Aceptar para crear la referencia y ahora en la carpeta de referencias de servicios, haga doble clic en la referencia que acaba de crear. Esto debería mostrarle el explorador de objetos con el espacio de nombres de la referencia de servicio que acaba de crear y que está resaltado. Haga doble clic en cualquiera de las clases dentro de este espacio de nombres y se abrirá el reference.cs relacionado que fue generado por Visual Studio.

Copie todo el contenido dentro de la declaración de espacio de nombres al archivo de su elección con el espacio de nombres que decida. También puede cambiar el nombre de la interfaz si planea manejar más de un mensaje saliente (el valor predeterminado debe ser NotificationPort). La interfaz tendrá referencias al espacio de nombres con el que lo construiste, pero puedes eliminar todo el espacio de nombres en el archivo porque todas las clases a las que hace referencia están en el mismo archivo.

Crear una nueva clase de servicio WCF. Elimine la interfaz que se crea automáticamente con el archivo svc y cambie el nombre de la interfaz al que acaba de copiar en el nuevo archivo.

De forma predeterminada, Visual Studio creó un método asíncrono que generaba errores cuando intenté implementarlo. Acabo de borrarlo de la interfaz y usé el método de notificación estándar.

Hice esto en VS2013 pero debería ser igual para 2010 y 2012 también. Asegúrese de que está usando ''Agregar referencia de servicio'' y no ''Agregar referencia web''. No olvide eliminar la referencia generada ya que no la usará.

Estoy considerando la implementación de la aplicación de escucha para la mensajería saliente de Salesforce.

El recorrido a través lo implementa utilizando el servicio web ASMX en desuso. El código se genera usando wsdl.exe con el modificador / serverInterface.

Aquí está el wsdl de mensajería saliente de Salesforce.

<?xml version="1.0" encoding="UTF-8"?> <definitions targetNamespace="http://soap.sforce.com/2005/09/outbound" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://soap.sforce.com/2005/09/outbound" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ent="urn:enterprise.soap.sforce.com" xmlns:ens="urn:sobject.enterprise.soap.sforce.com"> <types> <schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:enterprise.soap.sforce.com"> <!-- Our simple ID Type --> <simpleType name="ID"> <restriction base="xsd:string"> <length value="18"/> <pattern value=''[a-zA-Z0-9]{18}''/> </restriction> </simpleType> </schema> <schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:sobject.enterprise.soap.sforce.com"> <import namespace="urn:enterprise.soap.sforce.com" /> <!-- Base sObject (abstract) --> <complexType name="sObject"> <sequence> <element name="fieldsToNull" type="xsd:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/> <element name="Id" type="ent:ID" nillable="true" /> </sequence> </complexType> <complexType name="AggregateResult"> <complexContent> <extension base="ens:sObject"> <sequence> <any namespace="##targetNamespace" minOccurs="0" maxOccurs="unbounded" processContents="lax"/> </sequence> </extension> </complexContent> </complexType> <complexType name="Contact"> <complexContent> <extension base="ens:sObject"> <sequence> <element name="Email" nillable="true" minOccurs="0" type="xsd:string"/> <element name="FirstName" nillable="true" minOccurs="0" type="xsd:string"/> <element name="LastName" nillable="true" minOccurs="0" type="xsd:string"/> </sequence> </extension> </complexContent> </complexType> </schema> <schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://soap.sforce.com/2005/09/outbound"> <import namespace="urn:enterprise.soap.sforce.com" /> <import namespace="urn:sobject.enterprise.soap.sforce.com" /> <element name="notifications"> <complexType> <sequence> <element name="OrganizationId" type="ent:ID" /> <element name="ActionId" type="ent:ID" /> <element name="SessionId" type="xsd:string" nillable="true" /> <element name="EnterpriseUrl" type="xsd:string" /> <element name="PartnerUrl" type="xsd:string" /> <element name="Notification" maxOccurs="100" type="tns:ContactNotification" /> </sequence> </complexType> </element> <complexType name="ContactNotification"> <sequence> <element name="Id" type="ent:ID" /> <element name="sObject" type="ens:Contact" /> </sequence> </complexType> <element name="notificationsResponse"> <complexType> <sequence> <element name="Ack" type="xsd:boolean" /> </sequence> </complexType> </element> </schema> </types> <!-- Method Messages --> <message name="notificationsRequest"> <part element="tns:notifications" name="request"/> </message> <message name="notificationsResponse"> <part element="tns:notificationsResponse" name="response"/> </message> <!-- PortType --> <portType name="NotificationPort"> <operation name="notifications"> <documentation>Process a number of notifications.</documentation> <input message="tns:notificationsRequest"/> <output message="tns:notificationsResponse"/> </operation> </portType> <!-- Binding You need to write a service that implements this binding to receive the notifications --> <binding name="NotificationBinding" type="tns:NotificationPort"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="notifications"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <!-- Service Endpoint --> <service name="NotificationService"> <documentation>Notification Service Implementation</documentation> <port binding="tns:NotificationBinding" name="Notification"> <soap:address location="http://www.myserver.com/salesforceoutboundprototype/notificationport.svc"/> </port> </service> </definitions>

tldr necesito implementar NotificationBinding para que Salesforce pueda llamar a mi servicio web cuando ocurra un evento en su sistema.

Desde entonces me he dado cuenta de que svcutil no soporta de forma nativa el desarrollo de Contract-First.

Según el contrato SOA con WCF primero, usé WSCF.Blue para generar apéndices del lado del servidor desde Salesforce wsdl. Si bien el código compila el wsdl generado por mi servicio, no tiene la operación de notificaciones requerida.

Me pregunto qué me va mal.

Así que logré la implementación rápida de Salesforce wsdl utilizando wsdl.exe y / serverInterface y parece que el wsdl generado por la aplicación basada en asmx es bastante diferente de la aplicación basada en wcf.

Esta es la interfaz creada por wsdl.exe con / serverInterface

/// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.1")] [System.Web.Services.WebServiceBindingAttribute(Name="NotificationBinding", Namespace="http://soap.sforce.com/2005/09/outbound")] [System.Xml.Serialization.XmlIncludeAttribute(typeof(sObject))] public interface INotificationBinding { /// <remarks/> [System.Web.Services.WebMethodAttribute()] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)] [return: System.Xml.Serialization.XmlElementAttribute("notificationsResponse", Namespace="http://soap.sforce.com/2005/09/outbound")] notificationsResponse notifications([System.Xml.Serialization.XmlElementAttribute("notifications", Namespace="http://soap.sforce.com/2005/09/outbound")] notifications notifications1); }

Esta es la interfaz creada por WSCF.Blue

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] [System.ServiceModel.ServiceContractAttribute(Namespace="http://soap.sforce.com/2005/09/outbound", ConfigurationName="INotificationPort")] public interface INotificationPort { // CODEGEN: Generating message contract since the operation notifications is neither RPC nor document wrapped. [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")] [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)] [System.ServiceModel.ServiceKnownTypeAttribute(typeof(sObject))] notificationsResponse1 notifications(notificationsRequest request); }

Parecen ser bastante similares, así que no sé por qué el wsdl generado por estas aplicaciones sería tan diferente. ¿Vale la pena agregar wsdls (no quiero hacer más la pregunta de lo que ya está)?


Pasé por el mismo dolor de intentar que mi oyente OBM trabajara con WCF. Originalmente había configurado un OperationContract para el método de notificaciones. Después de la implementación, pronto me di cuenta de que sería necesario configurar un Contrato de datos, pero debido a limitaciones de tiempo y sin estar completamente seguro de si eso era todo lo que necesitaba hacer, simplemente cambié a un servicio web asmx que funcionaba.


Puede que no te guste lo que sugiero, pero creo que en realidad será la mejor opción para ti. Utilice ASMX. Tengo tres oyentes de OM y todos funcionan bien bajo 4.0

No sé quién difunde estas conclusiones erróneas sobre algunos técnicos de .NET 2.0, pero muchos de ellos no están obsoletos simplemente porque la comunidad dev se vio afectada por la novedad fetichista; ASMX es uno de ellos (también lo es Linq2SQL, etc.) Simplemente, WCF aún no está completo, no es totalmente compatible con WS y eso genera una gran cantidad de dolor con la integración de Salesforce (lo más doloroso es que WCF no admite encabezados de jabón donde Salesforce mantiene la información de la sesión).

Para obtener más información sobre por qué asmx NO es obsoleto, consulte aquí: .net 4.0 aún es compatible con asmx


Use svcutil para generar un proxy de cliente y simplemente elimine la implementación del proxy de cliente, y mantenga los contratos de servicio / datos. El contrato de servicio es simétrico desde el punto de vista de un cliente / servidor. He trabajado en proyectos sustanciales de contrato primero y encontré que esto es perfectamente adecuado.

Solo asegúrese de tener todos los WSDL externos disponibles para que svcutil los resuelva. Veo varias declaraciones de importación en tu texto WSDL arriba.

Por cierto, WSCF.Blue no está del todo desafortunadamente, ya que no se ha actualizado durante algunos meses y es poco probable que lo sea en el futuro. Lamentablemente, el desarrollador primario murió en un accidente automovilístico el año pasado (sí, en serio).


WSCF proporciona una herramienta de primer contrato con integración VS.