POSTing data to WebApi after update to 5.1.0 fails

2020-08-25 04:33发布

问题:

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

回答1:

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:

First clue:

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



回答3:

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.



回答4:

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



回答5:

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.