Подтвердить что ты не робот

Контракт-первый WCF для исходящей почты Salesforce

Я рассматриваю внедрение приложения-слушателя для Salesforce Outbound Messaging.

пройти через реализует его с использованием устаревшего веб-сервиса ASMX. Код создается с помощью wsdl.exe с ключом /serverInterface.

Здесь находится wsdl исходящих сообщений 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>

TL;DR - мне нужно реализовать NotificationBinding, чтобы Salesforce мог вызвать мой веб-сервис, когда в системе происходит событие.

Я так как понял, что svcutil не поддерживает Контракт-Первую разработку.

Как Контракт-первая SOA с WCF Я использовал WSCF.Blue для создания заглушек на стороне сервера из Salesforce wsdl. Пока код компиляции wsdl, сгенерированный моей службой, не имеет требуемой операции с уведомлениями.

Интересно, что я ошибаюсь?


Мне удалось быстро реализовать Salesforce wsdl с помощью wsdl.exe и /serverInterface, и похоже, что wsdl, созданный приложением asmx, сильно отличается от приложения на основе wcf.

Это интерфейс, созданный wsdl.exe с /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);
}

Это интерфейс, созданный 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);
}

Они кажутся довольно похожими, поэтому я не знаю, почему wsdl, сгенерированный этим приложением, будет таким другим? Стоит ли добавлять wsdls (не хотите задавать вопрос, если он уже есть)?

4b9b3361

Ответ 1

Вам может не понравиться то, что я предлагаю, но я считаю, что это будет лучший вариант для вас. Используйте ASMX. У меня есть три слушателя из OM, и все они работают очень хорошо под 4.0

Я не знаю, кто распространяет эти ошибки в отношении некоторых .NET2.0-техников, но многие из них, безусловно, не устарели только потому, что сообщество разработчиков было поражено фетишем новизны; ASMX является одним из них (также Linq2SQL и т.д.). WCF просто еще не завершен, он не полностью совместим с WS и вызывает много горя с интеграцией Salesforce (наиболее болезненным является то, что WCF не поддерживает заголовки мыла, где salesforce хранит информацию о сеансе).

Для получения дополнительной информации, почему asmx НЕ устарел, см. здесь: Поддерживает ли .net 4.0 asmx

Ответ 2

Используйте svcutil для создания прокси-сервера клиента и просто удалите реализацию прокси-сервера клиента и сохраните контракты на обслуживание/данные. Сервисный контракт симметричен с точки зрения клиента/сервера. Я работал над существенными контрактными проектами и нашел это вполне адекватным.

Просто убедитесь, что у вас есть все внешние WSDL, доступные для решения svcutil. Я вижу несколько операторов импорта в вашем тексте WSDL выше.

Кстати, WSCF.Blue не совсем доволен, к сожалению, поскольку он не обновлялся в течение нескольких месяцев и вряд ли будет таким в будущем. К сожалению, основной разработчик погиб в автокатастрофе в прошлом году (да, действительно.)

Ответ 3

Я пережил ту же боль, пытаясь заставить моего слушателя OBM работать с WCF. Первоначально я только установил OperationContract для метода уведомлений. После развертывания я вскоре понял, что необходимо будет установить контракт с данными, который я сделал, но из-за ограничений по времени и не совсем уверен, что это все, что мне нужно было сделать, просто переключилось на веб-службу asmx, которая работала.

Ответ 4

Я вычислил простой способ создания интерфейсов WCF из Salesforce WSDL с использованием встроенных инструментов Visual Studio. Я загрузил WSDL из Salesforce и сохранил его на своем рабочем столе. В Visual Studio перейдите в меню ссылок службы добавления в один из ваших проектов (неважно, где вы собираетесь удалить это). Для Url введите путь к WSDL, который вы загрузили локально (например, C:\Users\yourusername\Desktop\notification.wsdl)

Это должно привести к загрузке данных для службы. Нажмите "ОК", чтобы создать ссылку, и теперь в папке "Ссылки на службы" дважды щелкните ссылку, которую вы только что создали. Это должно показать вам браузер объектов с пространством имен только что созданной ссылки на службу. Дважды щелкните по любому из классов внутри этого пространства имен, и он откроет ссылку reference.cs, созданную визуальной студией.

Скопировать весь контент в объявлении пространства имен в файл по вашему выбору с любым пространством имен, которое вы решите. Вы также можете переименовать этот интерфейс, если вы планируете обрабатывать более одного исходящего сообщения (по умолчанию должен быть NotificationPort). Интерфейс будет иметь ссылки на пространство имен, с которым вы его построили, но вы можете удалить все пространство имен в файле, потому что все классы, к которым он относится, находятся в одном файле.

Создайте новый класс сервиса WCF. Удалите интерфейс, который автоматически создается с помощью файла svc и измените имя интерфейса на тот, который вы только что скопировали в новый файл.

По умолчанию Visual Studio создала некоторый метод async, который бросал ошибки, когда я пытался его реализовать. Я просто удалил его из интерфейса и использовал стандартный метод уведомления.

Я сделал это в VS2013, но он должен быть таким же для 2010 и 2012 годов. Убедитесь, что вы используете "Добавить ссылку на службу", а не "Добавить веб-ссылку". Не забудьте удалить сгенерированную ссылку, поскольку вы ее не используете.

Ответ 5

WSCF предоставляет инструмент для первого контракта с интеграцией VS.