WCF服务的服务呼叫流端点上的第三个呼叫失败(WCF Service service call to

2019-09-22 13:39发布

我在这里得到了快速的概述:

WCF SOAP服务正在运行通过HTTPS类型证书的信息凭证。 我有2个终点,我使用(除了墨西哥),1对我正常的服务电话,其他的流媒体文件。 这里是我的服务(编辑项目的一些名)的web.config:

<bindings>
  <wsHttpBinding>
    <binding name="wsHttpEndpointBinding">
      <security mode="TransportWithMessageCredential">
        <message clientCredentialType="Certificate" />
      </security>
    </binding>
  </wsHttpBinding>
  <basicHttpBinding>
      <binding name="streamBinding" transferMode="Streamed" messageEncoding="Mtom" maxReceivedMessageSize="2147483646">
          <security mode="TransportWithMessageCredential">
              <message clientCredentialType="Certificate" />
          </security>
      </binding>
  </basicHttpBinding>        
</bindings>
<services>
  <service behaviorConfiguration="Services.Behavior" name="MyInterface">
    <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="wsHttpEndpoint" contract="IMyInterface" />
    <endpoint address="stream" binding="basicHttpBinding" bindingConfiguration="streamBinding" name="streamEndpoint" contract="IMyInterface" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="Service.Behavior">
      <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <dataContractSerializer maxItemsInObjectGraph="2147483646" />
      <serviceCredentials>
        <serviceCertificate findValue="CN=Server.Temp.Dev" />
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

该服务有一个方法,DownloadDocument,那我测试。 下面是签名:

DocumentDownloadResponse DownloadDocument(DocumentDownloadRequest请求);

值得注意的服务引发异常时传递的数据是无效的,并DownloadDocument捕捉这些例外并传回响应对象的错误消息。

该DocumentDownloadRequest看起来是这样的:

[MessageContract]
public class DocumentDownloadRequest
{
    [MessageHeader]
    public string SecurityToken { get; set; }

    [MessageHeader]
    public string LoginName { get; set; }

    [MessageHeader]
    public string DocumentId { get; set; }
}

和DownloadDocumentResponse:

[MessageContract]
public class DocumentDownloadResponse : ServiceResponse<Stream>
{
    public DocumentDownloadResponse()
    {
        Data = Stream.Null;
    }

    [MessageHeader(MustUnderstand = true)]
    public bool Success { get; set; }

    [MessageHeader(MustUnderstand = true)]
    public string ErrorMessage { get; set; }

    [MessageBodyMember(Order = 1)]
    public Stream Data { get; set; }
}

以下是我把它从客户端:

        var soapServiceClient = new SoapServiceClient("streamEndpoint");
        bool success;
        Stream stream;
        string errorMessage =
            soapServiceClient.DownloadDocument(documentId, loginName, securityToken, out success, out stream);

        serviceClient.Close();

凡SecurityToken而LoginName是需要验证的项目。 什么奇怪的是,从我的测试客户端,当我打电话DownloadDocument有效的数据,我可以下载该文件完全多次,我想。 不过,如果我传递一个无效的LoginName或SecurityToken,我得到的指示不正确的数据(如预期)错误消息。 如果我通过在无效数据的3倍,但是,客户端超时。 运行该服务在本地我不明白这个问题,如预期everythign运行。 奇怪的是,whenI与小提琴手运行开放,我不明白这个问题。 当我的服务我的dev的服务器上运行,我有问题。

开发服务器上的配置相匹配的是我在本地运行。 使用SvcTraceTool我没有看到任何错误,但它仅记录了第2级成功的呼叫,而不是失败的一个。 它几乎让我觉得端点刚刚结束自己莫名其妙。

悬崖:

1)服务与2个端点,如果其中一个是流(在一个我很担心)。 2)能够使用流式端点调用方法与3)服务正确捕捉坏数据的2倍有效数据下载文件,挂在第3次。 在SvcTraceTool没有日志,客户端超时。

有任何想法吗?

谢谢

Answer 1:

为了回答罗德里戈,我想我会发布更多的详细信息:

首先,包装你生成的代理类的东西有点像这对正确处理错误:

public class ProxyWrapper<TServiceClientType, TResultType>
    where TServiceClientType : class, ICommunicationObject
{
    private static string _endPoint;

    public ProxyWrapper(string endPoint = "")
    {
        _endPoint = endPoint;
    }

    public TResultType Wrap(Func<string, TServiceClientType> constructWithEndpoint,
                                    Func<TServiceClientType, TResultType> codeBlock)
    {
        TResultType result = default(TResultType);
        TServiceClientType client = default(TServiceClientType);
        try
        {
            client = constructWithEndpoint(_endPoint);
            result = codeBlock(client);
            client.Close();
        }
        catch (Exception)
        {
            if (client != null)
            {
                client.Abort();
            }
            throw;
        }
        return result;
    }
}

然后,我有,围绕服务调用的包装客户端类。 这里的DownloadDocument方法:

    public MyServiceResponse<Stream> DownloadDocument(string loginName,
                                                            string documentId)
    {

        var proxyWrapper = new MyProxyWrapper<DocumentDownloadResponse>(StreamEndpoint);
        DocumentDownloadResponse response =
            proxyWrapper.Wrap((client) =>
            {
                Stream data;
                bool success;
                string errorMessage = client.DownloadDocument(documentId, loginName,
                                                              out success,
                                                              out data);
                return new DocumentDownloadResponse
                {
                    Data = data,
                    Success = success,
                    ErrorMessage = errorMessage
                };
            });

        var result = new MyServiceResponse<Stream>
        {
            Success = response.Success,
            ErrorMessage = response.ErrorMessage
        };

        if (!response.Success)
        {
            result.Data = null;
            response.Data.Close();
        }
        else
        {
            result.Data = response.Data;
        }

        return result;
    }

注:MyProxyWrapper从ProxyWrapper继承和指定的WCF客户端代理类。 现在的实际调用看起来是这样的:

var myClient = new MyClient();
var downloadDocumentResponse = myClient.DownloadDocument(someId);
                                using (
                                    Stream output =
                                        File.OpenWrite(someFilePath))
                                {
                                    downloadDocumentResponse.Data.CopyTo(output, 2048);
                                    downloadDocumentResponse.Data.Close();
                                }

请注意,我所说的.Close()在流,写入文件后,一旦这两个领域,而一旦是response.Success ==假。



文章来源: WCF Service service call to stream endpoint fails on 3rd call