3

Closed

WebAPI: Stream uploading under webhost is not working

description

I see that the stream uploading scenario is currently not supported in webhost. Selfhost scenario worked fine. It’s only issue with WebHost. Please see below exception details, actual issue in source code and the controller/action implementation.

Exception in event viewer:
Event message: Post size exceeded allowed limits.
Exception information:
Exception type: HttpException 
Exception message: Maximum request length exceeded.
at System.Web.HttpRequest.GetEntireRawContent()
at System.Web.HttpRequest.get_InputStream()
at System.Web.Http.WebHost.HttpControllerHandler.ConvertRequest(HttpContextBase httpContextBase)
at System.Web.Http.WebHost.HttpControllerHandler.BeginProcessRequest(HttpContextBase httpContextBase, AsyncCallback callback, Object state)
at System.Web.Http.WebHost.HttpControllerHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Issue:
The issue here actually is with the below highlighted statement requestBase.InputStream. It looks like we should be using GetBufferlessInputStream() in the case of buffering as the InputStream property calls seems to be buffering the whole stream and thus causing the below exception. TODO statement says so too.

From MSDN:
The InputStream property waits until the whole request has been received before it returns a Stream object. In contrast, the GetBufferlessInputStream method returns the Stream object immediately.
    HttpRequestMessage ConvertRequest(HttpContextBase httpContextBase)
    {
        ...
        // TODO: Should we use GetBufferlessInputStream? Yes, as we don't need any of the parsing from ASP
        request.Content = new StreamContent(requestBase.InputStream);
        ...
    }
Controller :
public class StreamController : ApiController
{
    [HttpPost]
    public long UploadStream(HttpRequestMessage request)
    {            
        var stream = request.Content.ReadAsStreamAsync().Result;
        byte[] buffer = new byte[1024];
        long totalBytesRead = 0;
        do
        {
            var bytesRead = stream.Read(buffer, 0, buffer.Length);
            if (bytesRead == 0)
                break;

            totalBytesRead += bytesRead;
        }
        while (true);

        return totalBytesRead;
    }
}
Closed Jul 18, 2012 at 8:14 PM by DRavva
Verified that it works fine.

comments

HongmeiG wrote Apr 20, 2012 at 11:29 PM

we should be using GetBufferlessInputStream instead Request.InputStream.

roncain wrote May 18, 2012 at 9:08 PM

This was fixed via commit http://aspnetwebstack.codeplex.com/SourceControl/changeset/changes/7d0e63289a74

To enable this scenario, register an IHostBufferPolicySelector in your global.asax.cs that returns false from UseBufferedInputStream()