none
WCF 4.5: An unexpected error occurred: The remote server returned an unexpected response: (413) Request Entity Too Large RRS feed

  • Question

  • I know that this question has been asked to death, yet the answer remains elusive. I've been through numerous posts with suggested solutions but this error continues to plague me. Any help would be greatly appreciated.

    I have a .Net 4.5 WCF service hosted on IIS which is consumed by an MVC5 web site on another IIS box. Communication works fine for the most part, but I need to allow the web site to upload files to the WCF service and the calls are all bombing out with the following error:

    An unexpected error occurred: The remote server returned an unexpected response: (413) Request Entity Too Large

    The methods being called in the web service take a single POCO as a parameter. The POCO contains a number of properties including a byte array for the contents of the file being uploaded. For example:

    public class ProofOfAddressRequest : RequestBase
    {
        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string Region { get; set; }
        public string City { get; set; }
        public string PostCode { get; set; }
        public string Country { get; set; }
        public string FileName { get; set; }
        public byte[] FileBytes { get; set; }
    }
    
    public ProofOfAddressResponse SubmitProofOfAddress(ProofOfAddressRequest data)
    {
        // TODO... Save the record
    }


    The web site's web.config is currently as follows:

    <configuration>
      <configSections/>
        
      <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="BasicHttpBinding_IUserService" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
              <readerQuotas maxDepth="32" maxStringContentLength="2097152" maxArrayLength="2097152" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
              <security mode="None"/>
            </binding>
          </basicHttpBinding>
        </bindings>
        <client>
          <endpoint address="http://localhost:58354/Services/UserService.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IUserService"
            contract="UserService.IUserService" name="BasicHttpBinding_IUserService" />
        </client>
      </system.serviceModel>
      
      <system.web>
        <customErrors mode="Off" />
        <authentication mode="None" />
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" maxRequestLength="4096"/>
      </system.web>
    
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
            <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    
    </configuration>


    And the web service's web.config is:

    <configuration>
    
      <configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      </configSections>  
    
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" maxRequestLength="4096"/>
      </system.web>
      
      <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="BasicHttpBinding" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
              <readerQuotas maxDepth="32" maxStringContentLength="2097152" maxArrayLength="2097152" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
              <security mode="None"/>
            </binding>
          </basicHttpBinding>
        </bindings>
       
        <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceWithMetadata">
              <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  
              Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <protocolMapping>
          <add binding="basicHttpBinding" scheme="http" />
          <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
        <!--
            To browse web app root directory during debugging, set the value below to true.
            Set to false before deployment to avoid disclosing web app folder information.
          -->
        <directoryBrowse enabled="true" />
      </system.webServer>
      
      <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
          <parameters>
            <parameter value="v11.0" />
          </parameters>
        </defaultConnectionFactory>
        <providers>
          <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        </providers>
      </entityFramework>
    </configuration>


    What I would like is to understand HOW to configure my config file(s) to allow a maximum upload size of say 2MB. If it is possible to pass the data in binary format rather than Base64 (or whatever) that would also be advantageous to decrease the bandwidth requirements between servers.

    Communication between sites is currently over HTTP in my dev environment, but I'll also need to configure for HTTPS for test/production. Bonus points for pointers on the additional config.

    Thanks in advance for any help you can provide on this. It's cost me a fair amount of time already and I'm no closer to a solution.


    • Edited by P.J.C Wednesday, May 28, 2014 10:46 AM edit
    Wednesday, May 28, 2014 9:50 AM

Answers

  • First of all, thanks to Amy and darnold924 for responding to my question - they managed to point me in a better direction direction, but ultimately (and after much trial and error) I found the answer I was looking for here

    In order to allow payloads (such as files or large arrays of data) OVER the default of 40KB to be sent to a WCF Service method, the changes required are predominantly in the web.config file of the WCF project. There is also one minor tweak required in the client's configuration, so we'll look at that first:

    <configuration> ... <system.serviceModel> <bindings> <basicHttpBinding> <!-- Large Message Upload (Begin) --> <binding name="BasicHttpBinding_IUserService" maxBufferPoolSize="2097152" maxReceivedMessageSize="2097152" /> <!-- Large Message Upload (End) --> <binding name="BasicHttpBinding_ISystemService" /> ... </basicHttpBinding> </bindings>

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


    When you first add a service reference to your client's project, Visual Studio automatically creates default binding and endpoint nodes in your config file. You'll need to add two new attributes to the binding node for your service: maxBufferPoolSize and maxReceivedMessageSize. Both attributes should have their values set to your desired file upload size limit IN BYTES. You'll also need to take note of the name for the next bit.

    That's if for the client configuration, so on to the WCF Service. Here's an extract from mine:

    <configuration>
       ...
      <system.serviceModel>
    
        <bindings>
          <basicHttpBinding>
            <!-- Large Message Upload (Begin) -->
            <binding name="BasicHttpBinding_IUserService"
                     maxBufferSize="2097152"
                     maxBufferPoolSize="2097152"
                     maxReceivedMessageSize="2097152"
                     closeTimeout="00:50:00" 
                     openTimeout="00:50:00" 
                     sendTimeout="00:50:00" 
                     receiveTimeout="00:50:00">
              <readerQuotas maxDepth="32" maxStringContentLength="100000"
                            maxArrayLength="2097152" maxBytesPerRead="4096"
                            maxNameTableCharCount="16384" />
              <security mode="None" />
            </binding>
            <!-- Large Message Upload (End) -->
          </basicHttpBinding>
        </bindings>
    
        <services>
          <!-- Large Message Upload (Begin) -->
          <service name="BlexEngine.Services.UserService"
                   behaviorConfiguration="ServiceWithMetadata">
            <endpoint name="Default"
                      binding="basicHttpBinding"
                      bindingConfiguration="BasicHttpBinding_IUserService"
                      contract="BlexEngine.Services.IUserService" />
          </service>
          <!-- Large Message Upload (End) -->
        </services>
        
        <behaviors>
          <serviceBehaviors>
            <!-- Large Message Upload (Begin) -->
            <behavior name="ServiceWithMetadata">
              <!-- Large Message Upload (End) -->
              
              <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  
              Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
        ...
      </system.serviceModel>
      ...
    </configuration>

    As you can see there are three changes required:

    1) Create a binding specifically for the service that you want to enable large file uploads for (my project publishes five services at the moment, but only one requires a larger file upload limit). Ensure that the value of the name attribute matches the name of the binding we noted in the client's web.config file. Copy the attributes and child nodes from the example above and modify as you see fit. All size values are, AKAIK, in bytes. 

    2) Jumping around a bit, we're going to move to the last change in the config extract next. Visual Studio creates a default behaviour node with all the correct settings, but does NOT set a name on that node, so add a name attribute and give it a value. ServiceWithMetadata was the value in the example I found, so that's what I used - I don't know if it really matters what you call it.

    3) Create a service node for your service. The name must be the fully qualified name of your service class and the behaviourConfiguration needs to be the name of the service node, as set in step 2). Within the service node you'll need to configure an endpoint, the bindingConfiguration of which needs to be set to the name of the binding setup in step 1) and the contract of which needs to be set to the fully qualified name of the interface your service class adheres to.

    That's it really. Figuring this out has taken far too long and I can't believe how complex the process has been or how little documentation there appears to be out there on this topic. To anyone suffering the same issue as I did: good luck! I hope that this post saves you the time I had to invest figuring this out the hard way.

    • Marked as answer by P.J.C Friday, May 30, 2014 9:44 AM
    Friday, May 30, 2014 9:44 AM

All replies

  • http://blogs.msdn.com/b/kaevans/archive/2008/01/24/wcf-and-custom-bindings.aspx

    You are probably going to need to use a Custom Binding in the service config to change default settings.

    Wednesday, May 28, 2014 10:51 PM
  • Hi,

    In your web service config file you have used the following:

    <basicHttpBinding>
            <binding name="BasicHttpBinding" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
              <readerQuotas maxDepth="32" maxStringContentLength="2097152" maxArrayLength="2097152" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
              <security mode="None"/>
            </binding>
    </basicHttpBinding>
    But you do not apply the above configuration to the endpoint, then by default the web service will use the default configuration. Also it will be better if you can increase the timeout value in the both server and client side. So please try to check the following:
    ............
    <basicHttpBinding>
           <binding name="BasicHttpBinding" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxReceivedMessageSize="2097152" 
    closeTimeout="00:50:00" openTimeout="00:50:00" sendTimeout="00:50:00" receiveTimeout="00:50:00> <readerQuotas maxDepth="32" maxStringContentLength="2097152" maxArrayLength="2097152" maxBytesPerRead="4096" maxNameTableCharCount="16384"/> <security mode="None"/> </binding> </basicHttpBinding> ................ <endpoint address="" binding="basicHttpBinding"
    bindingConfiguration="BasicHttpBinding"  
    contract="*****" />

    Best Regards,
    Amy Peng
     


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, May 29, 2014 8:12 AM
    Moderator
  •  

    So would I be right in saying that BOTH config files must have the exact same configuration within their <configuration> <system.serviceModel> <bindings> sections, and that the client must also have a <client> <endpoint> configured for each remote service referenced, where the binding attribute refers to the tag name of the relevant binding node and the bindingConfiguration attribute refers to the binding's name?

    (pauses for breath)

    My web service's config now looks like this:

    <configuration>
      ...
      <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="BasicHttpBinding_IUserService" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxReceivedMessageSize="2097152"
               closeTimeout="00:50:00" openTimeout="00:50:00" sendTimeout="00:50:00" receiveTimeout="00:50:00">
              <readerQuotas maxDepth="32" maxStringContentLength="2097152" maxArrayLength="2097152" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
              <security mode="None"/>
            </binding>
          </basicHttpBinding>
        </bindings>
        ...
      </system.serviceModel>
      ...
    </configuration>

    and the config for my web site is as follows:

    </configuration>
      ...
      <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="BasicHttpBinding_IUserService" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxReceivedMessageSize="2097152"
               closeTimeout="00:50:00" openTimeout="00:50:00" sendTimeout="00:50:00" receiveTimeout="00:50:00">
              <readerQuotas maxDepth="32" maxStringContentLength="2097152" maxArrayLength="2097152" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
              <security mode="None"/>
            </binding>
            <binding name="BasicHttpBinding_ISystemService" />
            ...
          </basicHttpBinding>
        </bindings>
        <client>
          <endpoint address="http://localhost:58354/Services/SystemService.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISystemService"
            contract="SystemService.ISystemService" name="BasicHttpBinding_ISystemService" />
          <endpoint address="http://localhost:58354/Services/UserService.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IUserService"
            contract="UserService.IUserService" name="BasicHttpBinding_IUserService" />
          ...
        </client>
      </system.serviceModel>
    </configuration>

    Unfortunately I'm still getting "An unexpected error occurred: The remote server returned an unexpected response: (413) Request Entity Too Large"

    Any further assistance you can provide would be greatly appreciated.

    Thursday, May 29, 2014 12:54 PM
  • Unfortunately I'm still getting "An unexpected error occurred: The remote server returned an unexpected response: (413) Request Entity Too Large"

    Any further assistance you can provide would be greatly appreciated.

    Again, if you don't override the bindings on the service-side with a custom binthing in the configuation file on the service-side, then the setttings are going to remain at their default settings.

    You can change settings on the client-side config as you have done, but doing the same thing on the service-side config without using a custom binding as shown in the link that was provided to you will leave the bindings on the service side unchanged leaving them at default settings.

    Thursday, May 29, 2014 1:25 PM
  • First of all, thanks to Amy and darnold924 for responding to my question - they managed to point me in a better direction direction, but ultimately (and after much trial and error) I found the answer I was looking for here

    In order to allow payloads (such as files or large arrays of data) OVER the default of 40KB to be sent to a WCF Service method, the changes required are predominantly in the web.config file of the WCF project. There is also one minor tweak required in the client's configuration, so we'll look at that first:

    <configuration> ... <system.serviceModel> <bindings> <basicHttpBinding> <!-- Large Message Upload (Begin) --> <binding name="BasicHttpBinding_IUserService" maxBufferPoolSize="2097152" maxReceivedMessageSize="2097152" /> <!-- Large Message Upload (End) --> <binding name="BasicHttpBinding_ISystemService" /> ... </basicHttpBinding> </bindings>

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


    When you first add a service reference to your client's project, Visual Studio automatically creates default binding and endpoint nodes in your config file. You'll need to add two new attributes to the binding node for your service: maxBufferPoolSize and maxReceivedMessageSize. Both attributes should have their values set to your desired file upload size limit IN BYTES. You'll also need to take note of the name for the next bit.

    That's if for the client configuration, so on to the WCF Service. Here's an extract from mine:

    <configuration>
       ...
      <system.serviceModel>
    
        <bindings>
          <basicHttpBinding>
            <!-- Large Message Upload (Begin) -->
            <binding name="BasicHttpBinding_IUserService"
                     maxBufferSize="2097152"
                     maxBufferPoolSize="2097152"
                     maxReceivedMessageSize="2097152"
                     closeTimeout="00:50:00" 
                     openTimeout="00:50:00" 
                     sendTimeout="00:50:00" 
                     receiveTimeout="00:50:00">
              <readerQuotas maxDepth="32" maxStringContentLength="100000"
                            maxArrayLength="2097152" maxBytesPerRead="4096"
                            maxNameTableCharCount="16384" />
              <security mode="None" />
            </binding>
            <!-- Large Message Upload (End) -->
          </basicHttpBinding>
        </bindings>
    
        <services>
          <!-- Large Message Upload (Begin) -->
          <service name="BlexEngine.Services.UserService"
                   behaviorConfiguration="ServiceWithMetadata">
            <endpoint name="Default"
                      binding="basicHttpBinding"
                      bindingConfiguration="BasicHttpBinding_IUserService"
                      contract="BlexEngine.Services.IUserService" />
          </service>
          <!-- Large Message Upload (End) -->
        </services>
        
        <behaviors>
          <serviceBehaviors>
            <!-- Large Message Upload (Begin) -->
            <behavior name="ServiceWithMetadata">
              <!-- Large Message Upload (End) -->
              
              <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  
              Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
        ...
      </system.serviceModel>
      ...
    </configuration>

    As you can see there are three changes required:

    1) Create a binding specifically for the service that you want to enable large file uploads for (my project publishes five services at the moment, but only one requires a larger file upload limit). Ensure that the value of the name attribute matches the name of the binding we noted in the client's web.config file. Copy the attributes and child nodes from the example above and modify as you see fit. All size values are, AKAIK, in bytes. 

    2) Jumping around a bit, we're going to move to the last change in the config extract next. Visual Studio creates a default behaviour node with all the correct settings, but does NOT set a name on that node, so add a name attribute and give it a value. ServiceWithMetadata was the value in the example I found, so that's what I used - I don't know if it really matters what you call it.

    3) Create a service node for your service. The name must be the fully qualified name of your service class and the behaviourConfiguration needs to be the name of the service node, as set in step 2). Within the service node you'll need to configure an endpoint, the bindingConfiguration of which needs to be set to the name of the binding setup in step 1) and the contract of which needs to be set to the fully qualified name of the interface your service class adheres to.

    That's it really. Figuring this out has taken far too long and I can't believe how complex the process has been or how little documentation there appears to be out there on this topic. To anyone suffering the same issue as I did: good luck! I hope that this post saves you the time I had to invest figuring this out the hard way.

    • Marked as answer by P.J.C Friday, May 30, 2014 9:44 AM
    Friday, May 30, 2014 9:44 AM