WCF Service服务调用流端点3日调用失败 [英] WCF Service service call to stream endpoint fails on 3rd call

查看:202
本文介绍了WCF Service服务调用流端点3日调用失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里得到了简要概述:

quick overview of what I've got here:

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

WCF Soap service is running over HTTPS, with Message credential of type certificate. I've got 2 endpoints that I use (besides mex), 1 for my normal service calls, the other for streaming files. Here's my web.config for the service (edited some names of items):

<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,我是测试。下面是签名:

The service has a method, DownloadDocument, that I'm testing. Here's the signature:

DocumentDownloadResponse DownloadDocument(DocumentDownloadRequest请求);

DocumentDownloadResponse DownloadDocument(DocumentDownloadRequest request);

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

It's worth noting the the service throws Exceptions when the data passed in is not valid, and DownloadDocument catches those exceptions and passes back the error message in the response object.

DocumentDownloadRequest看起来是这样的:

The DocumentDownloadRequest looks like this:

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

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

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

和DownloadDocumentResponse:

And 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; }
}

下面就是我把它从客户端:

Here's how I call it from the client:

        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的服务器上运行,我有问题。

Where SecurityToken and LoginName are items that need to validates. What's strange is that from my test client, when I call DownloadDocument with valid data, I am able to download the file perfectly as many times as I want. However, if I pass in an invalid LoginName or SecurityToken, I get error messages indicating incorrect data (as expected). If I pass in invalid data 3 times, however, the client times out. Running the service locally I don't get this issue, everythign runs as expected. Strangely enough, whenI run with fiddler open, I don't get this issue. When I run with the service on my dev server, I have the problems.

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

The configuration on the dev server matches what I run locally. Using the SvcTraceTool I don't see any errors, except that it only documents the first 2 successful calls, and not the one that failed. It almost makes me think the endpoint just closed itself somehow.

悬崖:

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

1) Service with 2 endpoints, one of if which is streaming (the one I'm concerned with). 2) Able to use streaming endpoint to call method to Download files with valid data 3) Service correctly catches bad data 2 times, hangs the 3rd time. No logs in SvcTraceTool, client times out.

任何想法?

感谢

推荐答案

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

In order to answer Rodrigo, I figured I'd post more details:

第一关,包装你生成的代理类的东西有点像这样,妥善处理错误:

First off, wrap your generated proxy class in something sort of like this to handle error properly:

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方式:

I then have a client class that wraps around the service calls. Here's the DownloadDocument method:

    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客户端代理类。现在的实际调用看起来是这样的:

Note: MyProxyWrapper inherits from ProxyWrapper and specified the WCF client proxy class. Now the actual call looks like this:

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 ==假的。

Note the two areas that that I call .Close() on the stream, once after writing the file, and once is response.Success == false.

这篇关于WCF Service服务调用流端点3日调用失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆