Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF problem with uploading large file, hosted in IIS

Tags:

wcf

I am trying to upload large files to a WCF Service hosted in IIS.

I am using Restful and Streaming method.

But I am not able to upload files which is more than 64KB.

I tried lot by changing all the size-related elements in web.config file, but failed to fix the issue.

Here is my code and config, please let me know if anyone find any issues in the code and how can I fix.

Operation Contract

[OperationContract]
[WebInvoke(UriTemplate = "/UploadImage/{filename}")]
bool UploadImage(string filename, Stream image);

Implementation of Operation Contract

public bool UploadImage(string filename, Stream image)
{
    try
    {
        string strFileName = ConfigurationManager.AppSettings["UploadDrectory"].ToString() + filename;

        FileStream fileStream = null;
        using (fileStream = new FileStream(strFileName, FileMode.Create, FileAccess.Write, FileShare.None))
        {
            const int bufferLen = 1024;
            byte[] buffer = new byte[bufferLen];
            int count = 0;
            while ((count = image.Read(buffer, 0, bufferLen)) > 0)
            {
                fileStream.Write(buffer, 0, count);
            }
            fileStream.Close();
            image.Close();
        }

        return true;
    }
    catch (Exception ex)
    {
        return false;
    }
}

web.config

  <system.serviceModel>
    <services>
      <service name="Service" behaviorConfiguration="ServiceBehavior">
        <endpoint address="http://localhost/WCFService1" behaviorConfiguration="web"
                  binding="webHttpBinding" bindingConfiguration="webBinding"
                  contract="IService">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <bindings>
      <webHttpBinding>
        <binding name="webBinding"
            transferMode="Streamed"
            maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
            openTimeout="00:25:00" closeTimeout="00:25:00" sendTimeout="00:25:00" 
            receiveTimeout="00:25:00" >
        </binding>
      </webHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

and

<httpRuntime maxRequestLength="2097151"/>

Service is hosted in hosted in IIS

Client side Code (console application)

private static void UploadImage()
{
    string filePath = @"F:\Sharath\TestImage\TextFiles\SampleText2.txt";
    string filename = Path.GetFileName(filePath);

    string url = "http://localhost/WCFService1/Service.svc/";
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + "UploadImage/" + filename);

    request.Accept = "text/xml";
    request.Method = "POST";
    request.ContentType = "txt/plain";

    FileStream fst = File.Open(filePath, FileMode.Open);
    long imgLn = fst.Length;
    fst.Close();
    request.ContentLength = imgLn;

    using (Stream fileStream = File.OpenRead(filePath))
    using (Stream requestStream = request.GetRequestStream())
    {
            int bufferSize = 1024;
            byte[] buffer = new byte[bufferSize];
            int byteCount = 0;
            while ((byteCount = fileStream.Read(buffer, 0, bufferSize)) > 0)
            {
                requestStream.Write(buffer, 0, byteCount);
            }
    }

    string result;

    using (WebResponse response = request.GetResponse())
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
            result = reader.ReadToEnd();
    }

    Console.WriteLine(result);
}

With this much of code I am able to upload 64KB of file, but when I try to upload a file of more than 64KB in size, I am getting error like,

The remote server returned an error: (400) Bad Request


i did what you told but still I am getting same problem, this is how my config looks like now, can you please tell me what is still missing here

<services>
  <service name="Service" behaviorConfiguration="ServiceBehavior">
    <endpoint address="http://localhost/WCFService1" behaviorConfiguration="web"
              binding="webHttpBinding" bindingConfiguration="webBinding"
              contract="IService">
      <identity>
        <dns value="localhost"/>
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>
<bindings>
  <webHttpBinding>
    <binding transferMode="Streamed"
             maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
             openTimeout="00:25:00" closeTimeout="00:25:00" sendTimeout="00:25:00" receiveTimeout="00:25:00"
             name="webBinding">
      <readerQuotas maxDepth="64" 
                    maxStringContentLength="2147483647" 
                    maxArrayLength="2147483647" 
                    maxBytesPerRead="2147483647" 
                    maxNameTableCharCount="2147483647"/>
    </binding>
  </webHttpBinding>
</bindings>
like image 843
Sharath Avatar asked Jun 11 '11 18:06

Sharath


3 Answers

The large data transfer issue with wcf:

I have wcf 4.0 service hosted on IIS 7, windows 2008 server. When I call my service with small data say 4K or 5K bytes then request get processed easily but while trying to upload large size it gave me following errors

  1. Bad Request 400
  2. File not found 404 13 as seen in IIS 7 logs
  3. There is no end point listening to the service "myservice url"

In all caseses I was able to transfer small data request with my client application to server but for large size message. Request failed.

I have tried all methods available to solve this issues but nothing worked for me.

After a scratching my head for a week and reading all articles and blogs finally I figured following

<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
        <binding name="myBinding" closeTimeout="00:10:00" maxBufferPoolSize="250000000" maxReceivedMessageSize="250000000" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" messageEncoding="Text">
        <readerQuotas maxDepth="4500000" maxStringContentLength="4500000" maxBytesPerRead="40960000" maxNameTableCharCount="250000000" maxArrayLength="4500000"/>
            </basicHttpBinding>
        </bindings>
    </system.serviceModel>
</configuration>



<system.web>

    <httpRuntime executionTimeout="4800" maxRequestLength="500000000"/>
</system.web>

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

<!-- other useful setting -->

<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

So I think It may help someone days....

like image 61
WaseemM Avatar answered Nov 18 '22 15:11

WaseemM


Based on the size mentioned by you, it seems error due to limit hit at the binding level i.e. readerQuota values. You can confirm if denial of server is due to exceeding the limit at binding level by capturing WCF traces. We can't see the configuration you've posted so, providing our best guess besed on information which is visible.

I'd capture WCF traces at verbose level to troubleshoot the issue.

Btw, have you tried increasing maxRequestLength? http://msdn.microsoft.com/en-us/library/system.web.configuration.httpruntimesection.maxrequestlength.aspx

HTH, Amit Bhatia

like image 38
amit Avatar answered Nov 18 '22 15:11

amit


what fixed 404 size of the message too big problem for me was a part of WaseemM's example:

<system.webServer>
    <security>
        <requestFiltering>
            <requestLimits maxAllowedContentLength="500000000"></requestLimits>
        </requestFiltering>
    </security>
like image 42
tridy Avatar answered Nov 18 '22 16:11

tridy