Web API 2 批量请求路由正确但无数据或500错误
Web API 2 Batch Request Routes Correctly But No Data or 500 Error
我最近创建了一个新的 Web API 2 项目,并且正在为我的 RESTful API 使用大部分默认脚手架。我正在尝试添加批处理支持并一直使用这两个资源作为指南:
https://aspnetwebstack.codeplex.com/wikipage?title=Web+API+Request+Batching
我添加了路由,并使用了框架提供的 DefaultHttpBatchHandler
所以我的 WebApiConfig.cs
看起来像这样:
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
using System.Web.Http.Batch;
namespace WebAPI_Test
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpBatchRoute(
routeName: "batch",
routeTemplate: "api/$batch",
batchHandler: new DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer)
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
我还有以下控制器:
using System;
using System.Web.Http;
namespace WebAPI_Test.Controllers
{
public class CustomersController : ApiController
{
public string Get(string id)
{
string val = String.Format("Customer: {0}", id);
return val;
}
}
}
我可以通过 Fiddler4 发出以下 HTTP 请求并获得成功响应:
GET http://example.com:8010/WebAPI_Test/api/customers/abs HTTP/1.1
User-Agent: Fiddler
Host: example.com:8010
我也可以成功命中批处理终点并获得 200 响应,但是,当我这样做时,我没有获得任何数据,而且我的控制器上的断点从未命中。使用以下请求:
POST http://example.com:8010/WebAPI_Test/api/$batch HTTP/1.1
User-Agent: Fiddler
Content-Type: multipart/mixed; boundary=abc101
Host: example.com:8010
Accept: multipart/mixed
Accept-Charset: UTF-8
Content-Length: 179
--abc101
Content-Type: application/http; msgtype=request
GET http://example.com:8010/WebAPI_Test/api/Customers/abc HTTP/1.1
Host: example.com:8010
--abc101--
我得到:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 84
Content-Type: multipart/mixed; boundary="1c950245-84e8-4c1b-8545-58e93cdd7b25"
Expires: -1
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 18 Feb 2016 00:09:54 GMT
--1c950245-84e8-4c1b-8545-58e93cdd7b25
--1c950245-84e8-4c1b-8545-58e93cdd7b25--
我注意到在上面提到的两个 link 中,后续请求都使用相对路径。所以我将我的请求正文修改为:
--abc101
Content-Type: application/http; msgtype=request
GET /WebAPI_Test/api/Customers/abc HTTP/1.1
Host: example.com:8010
--abc101--
但是,现在我只收到一个通用的 500: Internal Server Error
响应,我的 none 断点被命中。我想错误是从 .NET 库之一抛出的,但我没有得到堆栈跟踪。
在上面的第一个 link 中,作者使用的是 Owin 和自托管。我注意到他在他的 app
对象上调用了 UseWebApi
方法。虽然我是通过 IIS 托管的,但我还是决定试一试(诚然,运行 这里没有想法)。在我的 StartUp.cs
文件中,我有以下内容:
using Microsoft.Owin;
using Owin;
using System.Web.Http;
[assembly: OwinStartup(typeof(WebAPI_Test.Startup))]
namespace WebAPI_Test
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.UseWebApi(GlobalConfiguration.DefaultServer);
}
}
}
使用我上面提到的第一批 HTTP 请求(在请求正文中有完整路径)我得到了相同的结果:200 但没有数据并且永远不会命中控制器方法。
当我只尝试使用请求正文中的相对路径时,我仍然收到 500 错误,但我得到的不是通用 "An error as occurred" 消息,而是以下消息:
{
"Message": "An error has occurred.",
"ExceptionMessage":"Error parsing HTTP message header byte 5 of message System.Byte[].",
"ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Net.Http.HttpContentMessageExtensions.<ReadAsHttpRequestMessageAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Batch.DefaultHttpBatchHandler.<ParseBatchRequestsAsync>d__13.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Batch.DefaultHttpBatchHandler.<ProcessBatchAsync>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Batch.HttpBatchHandler.<SendAsync>d__0.MoveNext()"
}
我试图将我的 Customers 控制器 get 方法修改为 运行 异步(即 return 一个 Task<IHttpActionResult>
尽管因为我所做的只是 returning 一个字符串我知道那是多么毫无意义)但我仍然收到相同的错误消息。
我希望我遗漏了一些非常明显的东西。我没能找到任何解决此问题的 forums/questions/resources。如果有人有任何见解或帮助,将不胜感激。如果需要,我可以 post 更多我的配置代码(尽管它是非常标准的脚手架)。提前致谢!
这已通过更新 IIS 得到修复。
我应该早点更新这个,以防其他人看到它;如果还有其他人使用 Windows Server 2008/Windows 2007,这最终通过 IIS 更新得到解决。我希望我可以报告问题最初是什么,但是一旦它起作用,就不需要进一步调查(至少从我当时的雇主的角度来看不需要)。
我最近创建了一个新的 Web API 2 项目,并且正在为我的 RESTful API 使用大部分默认脚手架。我正在尝试添加批处理支持并一直使用这两个资源作为指南:
https://aspnetwebstack.codeplex.com/wikipage?title=Web+API+Request+Batching
我添加了路由,并使用了框架提供的 DefaultHttpBatchHandler
所以我的 WebApiConfig.cs
看起来像这样:
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
using System.Web.Http.Batch;
namespace WebAPI_Test
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpBatchRoute(
routeName: "batch",
routeTemplate: "api/$batch",
batchHandler: new DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer)
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
我还有以下控制器:
using System;
using System.Web.Http;
namespace WebAPI_Test.Controllers
{
public class CustomersController : ApiController
{
public string Get(string id)
{
string val = String.Format("Customer: {0}", id);
return val;
}
}
}
我可以通过 Fiddler4 发出以下 HTTP 请求并获得成功响应:
GET http://example.com:8010/WebAPI_Test/api/customers/abs HTTP/1.1
User-Agent: Fiddler
Host: example.com:8010
我也可以成功命中批处理终点并获得 200 响应,但是,当我这样做时,我没有获得任何数据,而且我的控制器上的断点从未命中。使用以下请求:
POST http://example.com:8010/WebAPI_Test/api/$batch HTTP/1.1
User-Agent: Fiddler
Content-Type: multipart/mixed; boundary=abc101
Host: example.com:8010
Accept: multipart/mixed
Accept-Charset: UTF-8
Content-Length: 179
--abc101
Content-Type: application/http; msgtype=request
GET http://example.com:8010/WebAPI_Test/api/Customers/abc HTTP/1.1
Host: example.com:8010
--abc101--
我得到:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 84
Content-Type: multipart/mixed; boundary="1c950245-84e8-4c1b-8545-58e93cdd7b25"
Expires: -1
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 18 Feb 2016 00:09:54 GMT
--1c950245-84e8-4c1b-8545-58e93cdd7b25
--1c950245-84e8-4c1b-8545-58e93cdd7b25--
我注意到在上面提到的两个 link 中,后续请求都使用相对路径。所以我将我的请求正文修改为:
--abc101
Content-Type: application/http; msgtype=request
GET /WebAPI_Test/api/Customers/abc HTTP/1.1
Host: example.com:8010
--abc101--
但是,现在我只收到一个通用的 500: Internal Server Error
响应,我的 none 断点被命中。我想错误是从 .NET 库之一抛出的,但我没有得到堆栈跟踪。
在上面的第一个 link 中,作者使用的是 Owin 和自托管。我注意到他在他的 app
对象上调用了 UseWebApi
方法。虽然我是通过 IIS 托管的,但我还是决定试一试(诚然,运行 这里没有想法)。在我的 StartUp.cs
文件中,我有以下内容:
using Microsoft.Owin;
using Owin;
using System.Web.Http;
[assembly: OwinStartup(typeof(WebAPI_Test.Startup))]
namespace WebAPI_Test
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.UseWebApi(GlobalConfiguration.DefaultServer);
}
}
}
使用我上面提到的第一批 HTTP 请求(在请求正文中有完整路径)我得到了相同的结果:200 但没有数据并且永远不会命中控制器方法。
当我只尝试使用请求正文中的相对路径时,我仍然收到 500 错误,但我得到的不是通用 "An error as occurred" 消息,而是以下消息:
{
"Message": "An error has occurred.",
"ExceptionMessage":"Error parsing HTTP message header byte 5 of message System.Byte[].",
"ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Net.Http.HttpContentMessageExtensions.<ReadAsHttpRequestMessageAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Batch.DefaultHttpBatchHandler.<ParseBatchRequestsAsync>d__13.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Batch.DefaultHttpBatchHandler.<ProcessBatchAsync>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Batch.HttpBatchHandler.<SendAsync>d__0.MoveNext()"
}
我试图将我的 Customers 控制器 get 方法修改为 运行 异步(即 return 一个 Task<IHttpActionResult>
尽管因为我所做的只是 returning 一个字符串我知道那是多么毫无意义)但我仍然收到相同的错误消息。
我希望我遗漏了一些非常明显的东西。我没能找到任何解决此问题的 forums/questions/resources。如果有人有任何见解或帮助,将不胜感激。如果需要,我可以 post 更多我的配置代码(尽管它是非常标准的脚手架)。提前致谢!
这已通过更新 IIS 得到修复。
我应该早点更新这个,以防其他人看到它;如果还有其他人使用 Windows Server 2008/Windows 2007,这最终通过 IIS 更新得到解决。我希望我可以报告问题最初是什么,但是一旦它起作用,就不需要进一步调查(至少从我当时的雇主的角度来看不需要)。