Post error: Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage

Any post in my Asp.net MVC generate this error:

Server Error in '/' Application.

Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 

[InvalidOperationException: Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.]   System.Web.HttpRequest.GetEntireRawContent() +12673515   System.Web.HttpRequest.get_InputStream() +61   System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext) +132   System.Web.Mvc.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory) +28   System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +248   System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +165   System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +536   System.Linq.Enumerable.ToList(IEnumerable`1 source) +80   System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext) +343   System.Web.Mvc.ControllerBase.get_ValueProvider() +57   System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +81   System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +153   System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) +839919   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag) +27   System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +50   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166   System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +827009   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag) +27   System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +401   System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +787114   System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +146   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +166   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag) +27   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +343   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +12622419   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18213

Full error details:

System.InvalidOperationException
Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.

System.InvalidOperationException: Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.
   at System.Web.HttpRequest.GetEntireRawContent()
   at System.Web.HttpRequest.get_InputStream()
   at System.Web.HttpRequestWrapper.get_InputStream()
   at System.Web.Mvc.JsonValueProviderFactory.GetDeserializedObject(ControllerContext controllerContext)
   at System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
   at Castle.Proxies.Invocations.ValueProviderFactory_GetValueProvider.InvokeMethodOnTarget()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Glimpse.Core.Extensibility.CastleInvocationToAlternateMethodContextAdapter.Proceed()
   at Glimpse.Core.Extensions.AlternateMethodContextExtensions.TryProceedWithTimer(IAlternateMethodContext context, TimerResult& timerResult)
   at Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context)
   at Glimpse.Core.Extensibility.AlternateTypeToCastleInterceptorAdapter.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.ValueProviderFactoryProxy.GetValueProvider(ControllerContext controllerContext)
   at System.Web.Mvc.ValueProviderFactoryCollection.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
   at System.Web.Mvc.ControllerBase.get_ValueProvider()
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state)
   at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Route config:

Default

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "home", action = "index", id = UrlParameter.Optional },
        namespaces: new string[] { "CreditoImobiliarioBB.Web.Controllers" }
    );
}

Areas

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Usuario_default"
        ,"usuario/{controller}/{action}/{id}"
        ,new { controller="home", action = "index", id = UrlParameter.Optional }
        , namespaces: new string[] { "CreditoImobiliarioBB.Web.Areas.Usuario.Controllers" }
    );
}

public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        name: "Relatorios",
        url: "{controller}/{id}/relatorio/{action}",
        defaults: new { id = 1 },
        constraints: new { id = @"^d+$" },
        namespaces: new string[] { "CreditoImobiliarioBB.Web.Areas.Relatorios" }
    );
}
public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        name: "Documentos",
        url: "{controller}/{id}/documento/{action}",
        defaults: null,
        constraints: new { id = @"^d+$" }
    );
}

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Just posting the findings here – as a summary of the chat – since others may get this error. Don’t hand out bounty, since I didn’t actually find the solution. 😉

The error itself is a result of trying to access BinaryRead, Form, Files or InputStream after something else has already accessed the request entity body stream (in other words, the content of the request) using a different method.

These “different methods” seem to include GetBufferedInputStream and GetBufferlessInputStream. These methods appear (not sure) to all be mutually exclusive. In other words, for a single request, you can only use one of:

  • BinaryRead(), Form, Files, InputStream (these will “cooperate” with each other),
  • GetBufferedInputStream(), or
  • GetBufferlessInputStream()

GetBufferedInputStream should cooperate with the “classic” access methods, according to the documentation – in fact, that’s its only difference from GetBufferlessInputStream. Nonetheless, in this case, the error stems from GetBufferedInputStream() being used, followed by InputStream.

The different methods are (inadequately) described in the documentation for the ReadEntityBodyMode property and its enum type.

A recent commit to the ASP.NET WebAPI changed its method of reading the body entity to GetBufferedInputStream() where before it used request.InputStream.

This appears to conflict with MVC’s JsonValueProviderFactory.GetDeserializedObject which uses the “classic” InputStream property to read the entity body. If we take the error message at face value, GetBufferedInputStream() has already been called, but it isn’t done reading when InputStream is accessed, so InputStream hasn’t been filled yet.

Need to do more testing, but a temporary fix (found by @KiranChalla) is to revert to a build from before the above-mentioned commit.

Method 2

We’ve reverted to using request.InputStream in Web API due to this problem (commit 9c76bb9090490541a453fcead75485ea50b88022).

JimmiTh’s answer correctly notes a discrepancy between the initial release notes and the implementation. As implied in the later documentation mentioned above (though it is not particularly clear), request.GetBufferlessInputStream(), request.GetBufferedInputStream() and request.InputStream (along with Form, Files, etc.) are three mutually exclusive methods of request body access.

It appears that, contrary to the initial release notes, request.GetBufferedInputStream() is not currently usable unless no other callers for the same request use any of InputStream, Form, Files, etc. I’m also following up to see if something better can be done compatibility between these two methods.

David

An update after talking with the product team:
Calling request.GetBufferedInputStream() or request.GetBufferlessInputStream() means “I’m handling the stream explicitly myself; take me into advanced mode where automatic stream processing is disabled.” However, in the case of buffered only, the members that normally rely on automatic stream processing (Form, Files, InputStream, etc.) are re-enabled after the buffered stream has been fully read.

So, as the exception message hints, touching any of those properties before finishing reading the stream will fail:

public ActionResult Index()
{
    Request.GetBufferedInputStream();
    var ignore = Request.InputStream;
    return View();
}

But doing so after finishing reading the stream will succeed:
public ActionResult Index()
{
    var stream = Request.GetBufferedInputStream();
    new StreamReader(stream).ReadToEnd();
    var ignore = Request.InputStream;
    return View();
}

The documentation isn’t particularly clear here; I’ll ask the product team if they can improve it.

We’re planning on switching back to GetBufferedInputStream in Web API; we’ll just make sure it plays better with MVC in terms of when this call happens relative to consuming the stream and MVC executing.

Method 3

I had the same issue when uploading files via Web API. Apparently “maximum request length exceeded” was hiding beneath this error, so increasing maxRequestLength in web.config solved it in my case.

Method 4

Today I learned that if you are using WebApi and your stream is a System.Net.Http.StreamContent.ReadOnlyStream and you try and read 0 bytes from it (stream.Read(buffer, 0, 0)), it will throw a System.InvalidOperationException, which when caught in a try/catch will show up as an exception with the message “Either BinaryRead, Form, Files, or InputStream was accessed before the internal storage was filled by the caller of HttpRequest.GetBufferedInputStream.”

I realize this seems silly, but you can do the same thing on a memory stream or file stream and no exception is thrown and in my case it was coming from MsgPackCli, hopefully this saves someone 4 hours.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x