WCF 服务和 QuickBooks Web 连接器之间没有匹配的合同

No matching contract between WCF Service and QuickBooks Web Connector

我正在尝试编写一个连接到 QuickBooks Web 连接器的小型 SOAP 服务器,但我在查找正确的合同时遇到了一些麻烦。我总是收到以下错误:

Web Connector

Method x cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

我创建了一个空的 ASP .NET Web 应用程序并添加了一个 WCF 服务。您会在这里找到 authenticate 方法的片段:

WCF 服务接口

[ServiceContract]
public interface IQuickBooks
{
    [OperationContract]
    AuthenticateResponse authenticate(Authenticate authenticateSoapIn);
}

WCF 服务实现

public class QuickBooks : IQuickBooks
{
    public AuthenticateResponse authenticate(Authenticate authenticateSoapIn)
    {
        return new AuthenticateResponse
        {
            AuthenticateResult = new[] { "1", "none" }
        };
    }
}

请求

[DataContract(Name = "authenticate")]
public class Authenticate
{
    [DataMember(Name = "strUserName", IsRequired = true)]
    public string Username { get; set; }

    [DataMember(Name = "strPassword", IsRequired = true)]
    public string Password { get; set; }
}

回应

[DataContract(Name = "authenticateResponse")]
public class AuthenticateResponse
{
    [DataMember(Name = "authenticateResult", IsRequired = true)]
    public string[] AuthenticateResult { get; set; }
}

Here you can find the WSDL from QuickBooks and my WSDL 输出。请注意,我只实现了 authenticate 方法进行测试。我想不匹配的 wsdl:types 会导致错误。在 QuickBooks 的原始 WSDL 中,authenticate type 有两个原始类型 usernamepassword

如何使用 QuickBooks Web 连接器实现 WCF 服务?我做错了什么?

附加信息

堆栈跟踪

The message with Action 'http://developer.intuit.com/authenticate' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
More info:
StackTrace =    at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
   at QBWebConnector.localhost.WCWebServiceDoc.authenticate(String strUserName, String strPassword)
   at QBWebConnector.localhost.WCWebService.authenticate(String strUserName, String strPassword)
   at QBWebConnector.SOAPWebService.authenticate(String UserName, String Password)
   at QBWebConnector.WebService.do_authenticate(String& ticket, String& companyFileName)

此答案描述了如何将 WCF 服务与 QuickBooks Web 连接器连接(例如 authenticate 方法)。我不完全确定它是否是最好的实现,但它有效,我想帮助其他有类似问题的人。附魔和额外的建议总是受欢迎的。

  1. 创建一个空的 ASP .NET Web 应用程序
  2. 添加 WCF 服务
  3. 定义服务契约
  4. 实施服务行为
  5. 定义必要的数据类型

创建服务合同

[ServiceContract(Namespace = QuickBooks.URL, Name = "QuickBooks")]
public interface IQuickBooks
{
    [OperationContract(Action = QuickBooks.URL + "authenticate")]
    AuthenticateResponse authenticate(Authenticate authenticateSoapIn);
}

创建服务行为

[ServiceBehavior(Namespace = QuickBooks.URL)]
public class QuickBooks : IQuickBooks
{
    public const string URL = "http://developer.intuit.com/";

    public AuthenticateResponse authenticate(Authenticate authenticateSoapIn)
    {
        // Check if authenticateSoapIn is valid

        var authenticateResponse = new AuthenticateResponse();
        authenticateResponse.AuthenticateResult.Add(System.Guid.NewGuid().ToString());
        authenticateResponse.AuthenticateResult.Add(string.Empty);

        return authenticateResponse;
    }
}

实现请求和响应类型

请求

[DataContract(Name = "authenticate")]
[MessageContract(WrapperName = "authenticate", IsWrapped = true)]
public class Authenticate
{
    [DataMember(Name = "strUserName", IsRequired = true)]
    [MessageBodyMember(Name = "strUserName", Order = 1)]
    public string Username { get; set; }

    [DataMember(Name = "strPassword", IsRequired = true)]
    [MessageBodyMember(Name = "strPassword", Order = 2)]
    public string Password { get; set; }

    public Authenticate()
    {
    }

    public Authenticate(string username, string password)
    {
        this.Username = username;
        this.Password = password;
    }
}

回应

[DataContract(Name = "authenticateResponse")]
[MessageContract(WrapperName = "authenticateResponse", IsWrapped = true)]
public class AuthenticateResponse
{
    [DataMember(Name = "authenticateResult", IsRequired = true)]
    [MessageBodyMember(Name = "authenticateResult", Order = 1)]
    public ArrayOfString AuthenticateResult { get; set; }

    public AuthenticateResponse()
    {
        this.AuthenticateResult = new ArrayOfString();
    }

    public AuthenticateResponse(ArrayOfString authenticateResult)
    {
        this.AuthenticateResult = authenticateResult;
    }
}

authenticateResponse

中使用的ArrayOfString
[CollectionDataContractAttribute(Name = "ArrayOfString", Namespace = QuickBooks.URL, ItemName = "string")]
public class ArrayOfString : List<string>
{
}

该方案符合SOAP协议,允许数据交换。