1
votes

I'm quite new to WCF services, and I just ran into this known issue, when the uploaded file is too big to upload. My situation is strange because I set both maxAllowedContentLength and maxRequestLength to a high number, so it should have no problems with uploading 300 MB files... With small files it works perfectly, so for me it seems like it just forgets about my settings. I tried so many ideas to solve this problem, so maybe I messed up things in my config file, there may be some unnecessary parts, but still I couldn't find the solution.

I'm working with IIS 10 and .Net 4.5.

My WCF Service configuration:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" maxRequestLength="4048576" requestLengthDiskThreshold="4048576" executionTimeout="3600" />
</system.web>
<system.serviceModel>
<behaviors>
  <serviceBehaviors>
    <behavior name="TileServiceBehavior">
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
    <behavior name="FileUploadServiceBehavior">
      <serviceMetadata httpGetEnabled="True" httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<protocolMapping>
  <add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<bindings>
  <basicHttpBinding>
    <binding name="BasicHttpBinding_ITileService" sendTimeout="01:00:00" maxBufferSize="5000000" /> 
    <binding name="HttpBinding_MTOM" 
              messageEncoding="Text" 
              transferMode="Streamed" 
              maxReceivedMessageSize="4294967294" 
              maxBufferSize="65536" 
              maxBufferPoolSize="65536" />
    <binding name="BasicHttpBinding_ITileServiceUpload" 
                closeTimeout="00:01:00" 
                openTimeout="00:01:00" 
                receiveTimeout="00:10:00" 
                sendTimeout="00:10:00" 
                allowCookies="false" 
                bypassProxyOnLocal="false" 
                hostNameComparisonMode="StrongWildcard" 
                maxBufferSize="65536" 
                maxBufferPoolSize="524288" 
                maxReceivedMessageSize="4294967294" 
                messageEncoding="Text" 
                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="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost/AEGIS.TileService/TileService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ITileServiceUpload" contract="AEGIS.TileService.ITileService" name="BasicHttpBinding_ITileServiceUpload" />
</client>
<services>
  <service behaviorConfiguration="FileUploadServiceBehavior" name="AEGIS.TileService.TileService">
    <endpoint address="winceStream" binding="basicHttpBinding" bindingConfiguration="HttpBinding_MTOM" contract="AEGIS.TileService.ITileService" />
  </service>
</services>
</system.serviceModel>
  <system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
<security>
  <requestFiltering>
    <requestLimits maxAllowedContentLength="4294967295" maxUrl="4294967295" maxQueryString="4294967295" />
  </requestFiltering>
</security>

The web.config file from my ASP.NET web app, where the service is referenced.

<system.serviceModel>
<bindings>
  <basicHttpBinding>
    <binding name="BasicHttpBinding_ITileService"/>
  </basicHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost/AEGIS.TileService/TileService.svc/winceStream" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ITileService" contract="TileService.ITileService" name="BasicHttpBinding_ITileService"/>
</client>

My upload method is implemented like this:

public void UploadFile(FileUploadMessage request)
    {
        string basePath = AppDomain.CurrentDomain.BaseDirectory + @"\Images\";
        string serverFileName = Path.Combine(basePath, request.Filename);

        using (FileStream outfile = new FileStream(serverFileName, FileMode.Create))
        {
            const int bufferSize = 65536; // 64K
            Byte[] buffer = new Byte[bufferSize];
            int bytesRead = request.FileByteStream.Read(buffer, 0, bufferSize);
            while (bytesRead > 0)
            {
                outfile.Write(buffer, 0, bytesRead);
                bytesRead = request.FileByteStream.Read(buffer, 0, bufferSize);
            }
        }
    }

Where FileUploadMessage is like this:

[MessageContract]
public class FileUploadMessage
{
    [MessageHeader(MustUnderstand = true)]
    public string Filename;
    [MessageBodyMember(Order = 1)]
    public Stream FileByteStream;
}

EDIT 1:

http://ipswitchft.force.com/kb/articles/FAQ/Unable-to-transfer-files-over-30MB-with-the-Web-Transfer-Module-or-Ad-Hoc-Transfer-Module-1307565986108

I found this article about this issue. Maybe my problem is not with the WCF service or config, but with IIS?

I set the requestLimits of the Default App Pool also to 1000000000. The error still appears.

Also in Option 3 the article writes about changing the ApplicationHost.config. The strange thing is that I don't have anything in that file about requestLimits. Maybe that's the main problem?

2
Make sure you have installed IIS request filtering module. Or try to reinstall it. (Go to Add remove windows features -> World Wide Web Services -> Security -> Request Filtering). This will add the module and it should update the applicationhost file.Dhanuka777

2 Answers

1
votes

Your are probably dealing with multiple "issues".

Remember to configure your Server AND Client accordingly!

First, i would configure my .NET runtime (WCF) and IIS behavior https://stackoverflow.com/a/6472631/1498669

NOTE: maxRequestLength is in KILOBYTES whereas maxAllowedContentLength is in BYTES


I would:


  1. set the default IIS parameter for your specific application (not for the whole machine!) using web.config in your base webfolder to a 'relatively' high value
<system.webServer>
 <security>
  <requestFiltering>

   <!-- maxAllowedContentLength defaults to 30000000 BYTES = 30MB --> 
   <!-- i use 100MB (100 *1024*1024)-->

   <requestLimits maxAllowedContentLength="104857600" /> 
  </requestFiltering> 
 </security>
</system.webServer>

  1. set the .NET Framework parameter to my expected 'max' value (at least a bit lower than the iis value) in KB to be able to catch the exception before iis presents me a error website (note: also raise the timeout for big data to transfer).
<system.web>

 <!-- maxRequestLength defaults to 4096 KILOBYTES = 4MB -->
 <!-- i use 80MB (80 *1024) -->
 <!-- please notes that if you use base64 encoded messages -->
 <!-- you have to calculate the overhead with CEIL(nBytes/3)*4 -->
 <!-- executionTimeout defaults to 110 SECONDS, i use 5 minutes -->

 <httpRuntime maxRequestLength="81920" executionTimeout="600" /> 
</system.web>

  1. after that, i configure my endpoints and their bindings

https://msdn.microsoft.com/en-us/library/ms733865.aspx

Also see https://stackoverflow.com/a/36931852/1498669 for the different attributes and their meaning.


As reference, the machine web.configs are located in (depending if you are using 2.0/4.0 and 32/64bits):

  • 32bit / net2.0-3.5
    C:\Windows\Microsoft.NET\Framework\v2.0.50727\Config\web.config
  • 32bit / net4.x
    C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config
  • 64bit / net2.0-3.5
    C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Config\web.config
  • 64bit / net4.x - this mostly gets used in Server2008R2 and higher
    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config

in these directories there are also:

  • web.config.default - you can copy that over web.config to reset your machine config, if you unintentionally altered the machine config!
  • web.config.comments - for a specific explanation of the attrs/elements

If you want to get in touch to all available elements/attributes - consult your visual studio installation directory, e.g:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Xml\Schemas\DotNetConfig45.xsd


Offtopic: as additional info to your security settings, see https://msdn.microsoft.com/en-us/library/ff648505.aspx

0
votes

You need to make similar changes to Web config as well.

You are using "BasicHttpBinding_ITileService" in the web. Therefore in the WCF config and Web config file needs to have similar configuration.

<binding name="BasicHttpBinding_ITileService" 
          maxBufferSize="2147483647" maxBufferPoolSize="2147483647" 
          maxReceivedMessageSize="2147483647">
         <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
               maxArrayLength="2147483647" maxBytesPerRead="2147483647" 
               maxNameTableCharCount="2147483647" />
     </binding>