Search code examples
c#wcfmtom

WCF Uploading 50Mg of file using MTOM


What is the best way to upload using WCF a 50MG file?

I thought MTOM would take care of that automatically.
I guess i was wrong...

The exception occurs even running on a LocalHost
(I'm assuming using an external IIS would be even worst).

Exception Message:

"An error occurred while receiving the HTTP response to http://localhost:7064/DataSyncService.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details."

Server Config:

    <system.serviceModel>
    <client>
        <remove contract="IMetadataExchange" name="sb" />
    </client>
    <bindings>
        <wsHttpBinding>
            <binding name="DataSyncBinding" messageEncoding="Mtom" maxReceivedMessageSize ="50000000" maxBufferPoolSize="50000000">
                <readerQuotas maxArrayLength="50000000" />
                <security mode="None" />
            </binding>
        </wsHttpBinding>
    </bindings>
    <services>
        <service behaviorConfiguration="Server.DataSyncServiceBehavior" name="Server.DataSyncService">
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="DataSyncBinding" name="DataSyncService"
                      contract="Server.IDataSyncService" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="Server.DataSyncServiceBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="false" />
</system.serviceModel>

Client Config:

    <system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="DataSyncService" closeTimeout="00:05:00" openTimeout="00:05:00"
                receiveTimeout="00:30:00" sendTimeout="00:30:00" bypassProxyOnLocal="false"
                transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Mtom" textEncoding="utf-8" useDefaultWebProxy="true"
                allowCookies="false">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00"
                    enabled="false" />
                <security mode="None">
                    <transport clientCredentialType="Windows" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="Windows" negotiateServiceCredential="true" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:7064/DataSyncService.svc"
            binding="wsHttpBinding" bindingConfiguration="DataSyncService"
            contract="DataSyncServiceReference.IDataSyncService" name="DataSyncService" />
    </client>
</system.serviceModel>

Thanks in advanced.


Solution

  • If the file is exactly 50 MB, then your maxReceivedMessageSize and maxArrayLength are set too low, since 50MB is actually 50 * 1024 * 1024 = 52428800 bytes. Also, the maxReceivedMessageSIze must account for the structure of the message itself (SOAP Envelope, etc.), not just the data.

    You could use streaming, that is the suggested way to go for large files. Unfortunately, it is not available with the wsHttpBinding, you may need to use something like basicHttpBinding or webHttpBinding to enable streaming.

    More on streaming here:

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