开发者

WCF Service hosted on IIS website with TransferMode = Streamed throws w3wp.exe OutOfMemory exception?

开发者 https://www.devze.com 2023-03-04 12:30 出处:网络
I have build a WCF service to upload and download files. Service: Hosted on IIS asp.net website: [ServiceContract]

I have build a WCF service to upload and download files.

Service: Hosted on IIS asp.net website:

[ServiceContract]
public interface IFileTransferService
{
 [OperationContract(IsOneWay = true)]
 void Upload(FileTransferRequest request);
}

[MessageContract()]
public class FileTransferRequest
{
 [MessageHeader(MustUnderstand = true)]
 public string FileName;

 [MessageBodyMember(Order = 1)]
 public System.IO.Stream Data;

}

[AspNetCompatibilityRequirements(RequirementsMode= AspNetCompatibilityRequirementsMode.Required)]
public class FileTransferService : IFileTransferService
{
 public FileTransferService()
 {
  HttpContext httpContext = HttpContext.Current;

  if (httpContext != null)
  {
   httpContext.Response.BufferOutput = false;
  }
 }

 public void Upload(FileTransferRequest request)
 {
  string fileName = System.Guid.NewGuid().ToString() + request.FileName;

  if (ConfigurationManager.AppSettings["UploadPath"] == null)
  {
   throw new ApplicationException("Missing upload path");
  }

  string uploadPath = "/OutputFeeds";
  string filePath = Path.Combine(Path.GetFullPath(HttpContext.Current.Server.MapPath(uploadPath)), fileName);
开发者_JS百科
  FileStream fs = null;
  try
  {
   fs = File.Create(filePath);
   byte[] buffer = new byte[1024];
   int read = 0;
   while ((read = request.Data.Read(buffer, 0, buffer.Length)) != 0)
   {
    fs.Write(buffer, 0, read);
   }
  }
  finally
  {
   if (fs != null)
   {
    fs.Close();
    fs.Dispose();
   }

   if (request.Data != null)
   {
    request.Data.Close();
    request.Data.Dispose();
   }
  }
 }    
}

Server config:

<system.serviceModel>
 <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
  </serviceHostingEnvironment>
 <bindings>
  <basicHttpBinding>
  <binding name="HttpBinding_MTOM" messageEncoding="Mtom" transferMode="Streamed" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
   <security mode="None">
   <transport clientCredentialType="None" />
   </security>
  </binding>

 </bindings>
 <services>

  <service behaviorConfiguration="FileTransferServiceBehavior"
  name="FileTransferService">
  <endpoint address="" binding="basicHttpBinding" bindingConfiguration="HttpBinding_MTOM"
   contract="IFileTransferService">
   <identity>
   <dns value="localhost" />
   </identity>
  </endpoint>
  <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

 </services>
 <behaviors>
  <serviceBehaviors>

  <behavior name="FileTransferServiceBehavior">
   <serviceMetadata httpGetEnabled="true" />
   <serviceDebug includeExceptionDetailInFaults="false" />
  </behavior>

  </serviceBehaviors>
 </behaviors>
 </system.serviceModel>

Client: Calling the above service from console application:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.serviceModel>
  <bindings>
   <basicHttpBinding>
    <binding name="BasicHttpBinding_IFileTransferService" closeTimeout="00:01:00"
     openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
     allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
     maxBufferSize="65536" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
     messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed"
     useDefaultWebProxy="true">
     <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
      maxBytesPerRead="4096" maxNameTableCharCount="16384" />
     <security mode="None">
      <transport clientCredentialType="None" proxyCredentialType="None"
       realm="">
       <extendedProtectionPolicy policyEnforcement="Never" />
      </transport>
      <message clientCredentialType="UserName" algorithmSuite="Default" />
     </security>
    </binding>

   </basicHttpBinding>
  </bindings>
  <client>
   <endpoint address="http://ht/FileTransferService.svc" binding="basicHttpBinding"
    bindingConfiguration="BasicHttpBinding_IFileTransferService"
    contract="HobbyTown.IFileTransferService" name="BasicHttpBinding_IFileTransferService" />

  </client>
 </system.serviceModel>
</configuration>

Client Upload Code:

 string inputFile = @"C:\Client\InputFeeds\FullInventory.zip";
 using (FileStream fs = new FileStream(inputFile, FileMode.Open))
 {
    FileTransferServiceClient proxy = new FileTransferServiceClient();
    proxy.Upload("Inventory.Zip", fs);
    //proxy.Upload(trIn);
 }

Note: If I change transfer mode to buffered in the client it works and however if Make the transfer mode on the client to Streamed it doesn't and throws outofmemory error.

Another post for same problem


I would wonder if the stream isn't being forced to behave as buffered on the service side. What is FileTransferRequest -- is that third-party? Streaming in WCF generally requires the stream be the only parameter in your exposed service method.

http://msdn.microsoft.com/en-us/library/ms733742.aspx

"Note that adding a second parameter to the following Echo or ProvideInfo operations causes the service model to revert back to a buffered strategy and use the run-time serialization representation of the stream. Only operations with a single input stream parameter are compatible with end-to-end request streaming.

This rule similarly applies to message contracts. As shown in the following message contract, you can have only a single body member in your message contract that is a stream. If you want to communicate additional information with the stream, this information must be a carried in message headers. The message body is exclusively reserved for the stream content."

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号