以错误的顺序执行的服务代码

时间:2016-02-11 11:12:50

标签: wcf

我的WCF服务有问题。似乎代码以意想不到的顺序执行。我的服务接受一个参数,该参数是具有文件附件(字节数组)和其他文本字段的数组的类。我的服务负责将这些文件保存在磁盘上。此外,每个服务和响应请求都记录在数据库中(以xml格式)。出于这个原因,我希望:

  1. 将文件保存在磁盘上;
  2. 使用文件二进制数据清除字段(该二进制数据不会保存在登录数据库中);
  3. 使用附件名称更新字段,其中包含保存文件的路径(此信息将在日志记录中);
  4. 当我在visual studio中本地测试服务时(不使用服务客户端代理,而是直接服务),一切正常。 问题是我正在测试IIS上托管的服务(v 7.5)。在我的服务中,在磁盘上保存文件后,我正在使用文件名更改字段,使用文件的二进制数据清除字段。问题是系统在磁盘上保存文件之前更新这些字段(结果是保存的文件为空或错误是错误/错误保存路径/)。当然,在我的服务中,代码中的第一个任务是将文件保存在磁盘上。 这就是我的例子:

    我正在使用VS2013,.NET Framework 4.5,WCF

    附件类

    public class Attachment
    {
        public string FilePath { get; set; }
        public byte[] FileBinary { get; set; }
    }
    

    服务代码(对问题有一些评论):

    public bool AddAttachments(List<Attachment> attachments)
        {
            bool result = false;
    
            string PathToSaveFile = String.Empty;
            string FileNameGuid = String.Empty;
    
            foreach (var a in attachments)
            {
                FileNameGuid = Guid.NewGuid().ToString();
                // step 1. Set file path and name
                PathToSaveFile = "C:\\FilesFromWCFService\\" + FileNameGuid + a.FilePath;
    
                try
                {
                   // step 2. saving file
                   // problem is here. Variable PathToSaveFile have value from step 1 and 3b (which i thing has not yet been executed)
                   // so value is i.e.: "C:\FilesFromWCFService\{Guid}{FilePath}File localization: {PathToSaveFile}"
                   // and a.FileBinary is equal to byte[0] step 3a.
                   // it seems like steps 3a and 3b is executed before step 2
                   File.WriteAllBytes(PathToSaveFile, a.FileBinary);
                   result = true;
                }
                catch (Exception ex)
                {
                    throw new Exception("Error while saving file on disk");
                }
    
                // step 3a. clear file binary data (that data won't be saved in db log)
                a.FileBinary = new byte[0];
                // step 3b. update file localization on server
                a.FilePath = String.Format("File localization: {0}", PathToSaveFile);
    
                // reset variables
                PathToSaveFile = String.Empty;
                FileNameGuid = String.Empty;
            }
    
            Return result;
        }
    

    当我在iis上调试服务时(通过在VS中附加iis进程)并在第一行服务代码上设置断点,我可以看到字节文件内容(a.FileBinary)和文件路径(a.FilePath)是从步骤3a和3b设置(不是参数列表附件中的原始。

    如果我评论更改文件路径并重置文件内容(步骤3a和步骤3b),那么一切正常(但当然在日志中以二进制格式保存文件 - 我想避免使用)。

    服务配置:

    <services>
      <service name="AddAttachments">
        <endpoint address="AddAttachmentsService" behaviorConfiguration="ServiceEndpointBehavior"
          binding="basicHttpBinding" name="httpEndpoint" contract="PlayService.IAddAttachmentsService" />
        <endpoint address="AddAttachmentsService" behaviorConfiguration="ServiceEndpointBehavior"
          binding="netTcpBinding" name="tcpEndpoint" contract="PlayService.IAddAttachmentsService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:65045/" />
            <add baseAddress="net.tcp://localhost:65055/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding messageEncoding="Mtom"
                 closeTimeout="00:10:00"
                 sendTimeout="00:10:00"
                 maxBufferPoolSize="524288"
                 maxReceivedMessageSize="2147483647">
        </binding>
      </basicHttpBinding>
      <netTcpBinding>
        <binding transferMode="Streamed"
                 closeTimeout="00:10:00"
                 sendTimeout="00:10:00"
                 maxBufferPoolSize="524288"
                 maxReceivedMessageSize="2147483647"></binding>
      </netTcpBinding>
    </bindings>
    <behaviors>
    
      <endpointBehaviors>
        <behavior name="ServiceEndpointBehavior" >
          <logMessage_2 />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="mexBehaviour">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    

    客户端配置:

    <system.serviceModel>
      <bindings>
        <basicHttpBinding>
          <binding name="httpEndpoint" messageEncoding="Mtom"
                   closeTimeout="00:10:00"
                   sendTimeout="00:10:00"
                   maxBufferPoolSize="524288"
                   maxReceivedMessageSize="2147483647"></binding>
          <!--<binding name="httpEndpoint" messageEncoding="Mtom" />-->
        </basicHttpBinding>
        <netTcpBinding>
          <binding name="tcpEndpoint"
               closeTimeout="00:10:00"
               sendTimeout="00:10:00"
               maxBufferPoolSize="524288"
               maxReceivedMessageSize="2147483647"></binding>
          <!--<binding name="tcpEndpoint" transferMode="Streamed" />-->
        </netTcpBinding>
      </bindings>
      <client>
        <endpoint address="http://localhost/MyService/MyService.svc/AddAttachmentsService"
            binding="basicHttpBinding" bindingConfiguration="httpEndpoint"
            contract="PService.IAddAttachmentsService" name="httpEndpoint" />
        <endpoint address="net.tcp://myComp/MyService/PlayService.svc/AddAttachmentsService"
            binding="netTcpBinding" bindingConfiguration="tcpEndpoint"
            contract="PService.IAddAttachmentsService" name="tcpEndpoint">
          <identity>
            <servicePrincipalName value="host/MyComp" />
          </identity>
        </endpoint>
      </client>
    </system.serviceModel>
    

    当我使用netTcpBinding或basicHttpBinding时,问题是一样的。

    我是WCF的新手,我不知道我还能在网上搜索什么。我读过有关流媒体的信息(当我在Streamed上设置transferMode时没有区别),关于并发性和实例化(我设置了不同的选项 - 但我认为这与此问题无关)。

    如果我收到的信息很少,请告诉我。

1 个答案:

答案 0 :(得分:0)

好的,我发现了问题所在:

  1. 当我测试我的服务时,我将参数(对象)传递给第一次服务调用,然后传递给服务的第二次调用(但是第一次调用时对象被更改了) - 我忘记了对象是通过引用传递:)

  2. 我发现我无法在服务调用中更改消息(用于记录目的) - 我通过消息检查器(方法AfterReceiveRequest)记录消息,该消息检查器早于服务执行调用。