9
votes

I have an web app that use webapi for loading / saving data All used to work ok/ Today I found that there is an updated to ASP.NET MVC / webapi, and I installed the update But after that POSTing data with jquery no longer works. I made no change either in client code or in webapi controller.

My typical POSt statement looks as below:

showProgress(true, self.PanelID(), 'Saving...')
j$.ajax({
    type: "POST",
    url: uri,
    data: dataObj,
    error: function (jqXHR, status, error) {
        showProgress(false);
        GLOBAL.setMessage(self, 'Error saving ' + opType + '<br>' + error, true);
    },
    success: function (data, status, jqXHR) {
        showProgress(false);
        if (status === 'success') {
        GLOBAL.setMessage(self, opType + " saved ok");
        //....

The $.ajax code gets the following error

"An error has occurred."

ExceptionMessage
    "This method or property is not supported after HttpRequest.Form, Files, InputStream, or BinaryRead has been invoked."

ExceptionType
    "System.Web.HttpException"

StackTrace
at System.Web.HttpRequest.GetInputStream(Boolean persistEntityBody, Boolean disableMaxRequestLength) 
at System.Web.HttpRequestWrapper.GetBufferedInputStream() 
at System.Web.Http.WebHost.SeekableBufferedRequestStream..ctor(HttpRequestBase request) 
at System.Web.Http.WebHost.HttpControllerHandler.c__DisplayClass11.b__b() at System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent.get_StreamContent() at System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent.CreateContentReadStreamAsync() at System.Net.Http.HttpContent.ReadAsStreamAsync() at System.Net.Http.HttpContentExtensions.d__0`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
at System.Web.Http.ModelBinding.FormatterParameterBinding.d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
at System.Web.Http.Controllers.HttpActionBinding.d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
at System.Web.Http.Filters.AuthorizationFilterAttribute.d__2.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__0.MoveNext()"

These are the nuget packages from my solution

  package id="Microsoft.AspNet.Mvc" version="5.1.0" targetFramework="net45" 
  package id="Microsoft.AspNet.Razor" version="3.1.0" targetFramework="net45" 
  package id="Microsoft.AspNet.SignalR.Client" version="2.0.1" targetFramework="net45" 
  package id="Microsoft.AspNet.Web.Optimization" version="1.1.2" targetFramework="net45" 
  package id="Microsoft.AspNet.WebApi" version="5.1.0" targetFramework="net45" 
  package id="Microsoft.AspNet.WebApi.Client" version="5.1.0" targetFramework="net45" 
  package id="Microsoft.AspNet.WebApi.Core" version="5.1.0" targetFramework="net45" 
  package id="Microsoft.AspNet.WebApi.HelpPage.VB" version="5.1.0" targetFramework="net45" 
  package id="Microsoft.AspNet.WebApi.OData" version="5.1.0" targetFramework="net45" 
  package id="Microsoft.AspNet.WebApi.WebHost" version="5.1.0" targetFramework="net45" 
  package id="Microsoft.AspNet.WebPages" version="3.1.0" targetFramework="net45" 
  package id="Microsoft.Bcl" version="1.1.6" targetFramework="net45" 
  package id="Microsoft.Bcl.Build" version="1.0.13" targetFramework="net45" 
  package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net45" 
  package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net45" 
  package id="Microsoft.Net.Http" version="2.2.18" targetFramework="net45" 
  package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" 

Does anyone knows what could be the problem? Any idea on how to fix it?

EDIT

Sample controller code:




Public Class ImportController
    Inherits ApiController

    
    
    Public Function SaveImportSession(sessid As string,  entity As SIImportSessionDTO) As HttpResponseMessage

        Try
            InspectionData.SaveImportSession(sessid, entity)
            Dim response = Request.CreateResponse(HttpStatusCode.Accepted)
            Return response
        Catch ex As HttpResponseException
            Throw
        Catch ex As Exception
            Throw New HttpResponseException(Request.CreateResponse(Of String)(HttpStatusCode.InternalServerError, ex.Message))
        End Try
    End Function

I'm using only attribute-based routes, and this is my webapi route config

Public Shared Sub Register(ByVal config As HttpConfiguration)

        config.MapHttpAttributeRoutes()

        config.Routes.MapHttpRoute( _
            name:="DefaultApi", _
            routeTemplate:="api/{controller}/{id}", _
            defaults:=New With {.id = RouteParameter.Optional} _

The problem, my server side code is not even reached, something else on the pipeline throw the exception

Thanks

5
could you show what the server side code looks likeWarrenn enslin
This looks like a bug that we have encountered before...can you please give us the exact repro steps by which you are seeing this...do you have any Web API buffer policy set explicitly? also can you note down the sequence which is causing this...Kiran Challa
Continuing on my previous comment...do you have any route constraints on your routes...i ask this because this was one of the paths which was causing this kind of issue..Kiran Challa
No, I don't have Web API buffer policy set explicitly (I don't know what is that)bzamfir
Thanks for the update...From the error it appears that the request stream is being read by other piece of code...Would it be possible for you to give a standalone repro so that we can dig deeper to see the root cause..Kiran Challa

5 Answers

6
votes

I found the problem.

My post code uses $.ajax(...), as shown in initial message.

But jquery's .ajax post data as application/x-www-form-urlencoded. This worked in previous versions of WebAPI, but in latest update it seems it doesn't accept application/x-www-form-urlencoded by default.

I changed content type to application/json, and I had to convert data to json, and this solved the problem.

So, instead of

j$.ajax({
    type: "POST",
    url: uri,
    data: dataObj,
    success: function(...)

I had to change to

j$.ajax({
    type: "POST",
    url: uri,
    data: JSON.stringify(dataObj),
    contentType: "application/json; charset=utf-8",
    success: function(...)
2
votes

First clue:

Removing enableCrossAppRedirects="true" from Authentication settings of web.config resolved the issue in my case. Thanks to @kiran-challa

2
votes

Ok, I found the fix for this without a work around.

Refer to this thread: h t t p : / / a s p n e t w e b s t a c k . c o d e p l e x . c o m/discussions/524616

This is a bug in 5.1 - it is resolved in a nightly build See: https://aspnetwebstack.codeplex.com/ and specifically Signed nightly builds:

"Nightly builds can be used with Visual Studio 2010 SP1 or Visual Studio 2012. To use the nightly build: 1.In your Package Manager settings add the following package source: ....
2.Add or update to the latest build of ASP.NET. The nightly build is labeled (nightly YYYY MMM DD). "

this fixed the post issues for me (no need to use JSON.stringify anymore) and also fixed multi-part posting for a module that was uploading a file.

Hope this helps someone else! And hopefully there will be a proper patch for this soon.

2
votes

A fix for this issue was published today. Update your packages to the latest (5.1.1) and you should be good to go.

0
votes

sorry, I am not allowed to comment yet so I have to add an answer.

I have the exact same issue after updating to 5.1.

I was able to get past this error by making a similar change (or actually by specifying the contentType), however, now the controller method receives a null object.

This has affected all POSTS in the app - all previously working.