0

I am developing a sample Xamarin.Forms app, which take a photo and after that upload it to a remote server. The upload part is handled by a WCF service deployed on remote IIS.

The client part is ok, but when the flow arrive to the server part, I receive this error:

System.Net.WebException: There was an error in processing web request: Status code 413(RequestEntityTooLarge): Request Entity Too Large

I tried to increase the maxi size of the message, both in WCF's web.config and in the site where the service is deployed.

Below the service's web.config:

<?xml version="1.0" encoding="utf-8"?>
<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>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.6.1" />
    <httpRuntime targetFramework="4.6.1" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="GlobalEndpoint">
          <dataContractSerializer maxItemsInObjectGraph="1365536" />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="GlobalBehavior">
      <dataContractSerializer maxItemsInObjectGraph="1365536" />
    </behavior>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>       
        <binding
          name="BasicHttpBinding_IQuery_service"
          maxBufferPoolSize="2147483647"
          maxReceivedMessageSize="2147483647"
          maxBufferSize="2147483647" 
          transferMode="Streamed">
          <readerQuotas maxDepth="2000000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
        </binding>       
      </basicHttpBinding>     
    </bindings>
    <client>
      <endpoint address="http://path/to/service.svc"
          binding="webHttpBinding" bindingConfiguration="BasicHttpBinding_IQuery_service"
          contract="IQuery_service" name="BasicHttpBinding_IQuery_service" />
    </client>
    <protocolMapping>
        <add binding="webHttpBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <directoryBrowse enabled="true" />
  </system.webServer>

Below the settings of the Configuration editor of the site, where is deployed the WCF service:

enter image description here

Below the method which I call for uploading the image:

public bool UploadToFolder(byte[] file_bytes, string file_name)
        {
            bool isSuccess = false;
            FileStream fileStream = null;
            //Get the file upload path store in web services web.config file.  
            string strFolderPath = System.Configuration.ConfigurationManager.AppSettings.Get(@"dest\path");
            try
            {
                if (!string.IsNullOrEmpty(strFolderPath))
                {
                    if (!string.IsNullOrEmpty(file_name))
                    {
                        string strFileFullPath = strFolderPath + file_name;
                        fileStream = new FileStream(strFileFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                        // write file stream into the specified file  
                        using (System.IO.FileStream fs = fileStream)
                        {
                            fs.Write(file_bytes, 0, file_bytes.Length);
                            isSuccess = true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return isSuccess;
        }

I don't know if this is the best way to perform an upload to remote server from Xamarin app, any suggest is appreciated.

EDIT

Already tried to increment maxReceivedMessageSize in web.config, without success.

Such as I read on the main page of the service, I run the command svcutil.exe http://server_address/path/to/service.svc?wdsl, after that I added the file.cs to my solution and from this I call the varius methods.

The piece of code where I call the upload method:

try
{       
    Query_serviceClient client = new Query_serviceClient(http_binding, endpoint_address);
    client.UploadToTempFolder(filebyte, filename);
    client.Close();
}
catch (Exception ex)
{
    DisplayAlert("ERROR", ex.ToString(), "OK");
}  
Leonardo Bassi
  • 184
  • 1
  • 2
  • 14

2 Answers2

0

Before answering the question, we should figure out the way you call the WCF service. This determined which way you want to call the service, then apply the configuration on the right service(Soap web service or Rest style).
According to the above service configuration, it is invalid to host the service in IIS, namely, the WCF service is running improperly, not to mention that the error occurred in the invocation. If we tried to access the service WSDL, we will see the error details. Are you using a client proxy to upload the image, or directly instantiating an HttpClient class to create a post request to the service endpoint address?
If you chose the first way to upload the image, please refer to the below configuration.

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding
          name="mybinding"
          maxReceivedMessageSize="2147483647">
        </binding>
      </basicHttpBinding>
    </bindings>
    <protocolMapping>
      <add binding="basicHttpBinding" scheme="http" bindingConfiguration="mybinding"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

If you want to create a Restful style WCF service, i.e., the second choice, please refer to the below configuration.

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior>
          <webHttp />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <webHttpBinding>
        <binding name="rest" maxReceivedMessageSize="2147483647">
        </binding>
      </webHttpBinding>
    </bindings>
    <protocolMapping>
      <add binding="webHttpBinding" scheme="http" bindingConfiguration="rest"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

Feel free to let me know if the problem still exists.

Abraham Qian
  • 7,117
  • 1
  • 8
  • 22
  • I am new on this enviroment, but probably I use the first way (using a client proxy to upload the image). I provide some new information in the edit section, if you want to take a look. – Leonardo Bassi Jan 10 '20 at 09:05
  • Yes, you are using the first one. and please generate a client proxy using Add Service Reference. https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client – Abraham Qian Jan 10 '20 at 09:20
  • Besides, please ensure that the service is running properly before you create a call to the service. – Abraham Qian Jan 10 '20 at 09:24
  • I added the service reference such as you suggested, but I have only Async methods in the reference.cs, so I got this error: "**Error in deserializing body of request message for operation ''. OperationFormatter encountered an invalid Message body**". – Leonardo Bassi Jan 10 '20 at 10:39
0

The solution is change the method which does the upload.

So finally to upload the image I use this simple and clean solution:

public void UploadFile(Stream file_stream)
        {
            using (var output = File.Open("dest/for/image.jpg", FileMode.Create, FileAccess.ReadWrite))
            {
                file_stream.CopyTo(output);
            }
        }
Leonardo Bassi
  • 184
  • 1
  • 2
  • 14