我一直在尝试将一些OWIN中间件插入到现有的WebApi项目中。我的启动文件最初只包含以下几行代码:
application.UseOAuthBearerAuthentication(newOAuthBearerAuthenticationOptions());
application.UseWebApi(config);
使用此配置后,我偶尔会在iisreset之后收到格式错误的响应(如Fiddler所示),这是由于中间件在响应已发送后尝试添加标头引起的。这被报告为异常情况:
Server cannot append header after HTTP headers have been sent.
我重新编译了Microsoft.Owin.Security.OAuth,添加了一些额外的跟踪代码以显示事件发生的顺序,结果如下:
Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationMiddleware Information: 0 : : OAUTH: Authenticating...
System.Web.Http.Request: ;;http://localhost:555/entityinstance/member
System.Web.Http.Controllers: WebHostHttpControllerTypeResolver;GetControllerTypes;:
System.Web.Http.Controllers: WebHostHttpControllerTypeResolver;GetControllerTypes;:
System.Web.Http.MessageHandlers: LogHandler;SendAsync;:
System.Web.Http.Controllers: DefaultHttpControllerSelector;SelectController;Route='entityDefinitionName:member,controller:EntityInstance'
System.Web.Http.Controllers: DefaultHttpControllerSelector;SelectController;EntityInstance
System.Web.Http.Controllers: HttpControllerDescriptor;CreateController;:
System.Web.Http.Controllers: WindsorCompositionRoot;Create;:
System.Web.Http.Controllers: WindsorCompositionRoot;Create;Loyalty.Services.WebApi.Controllers.EntityInstanceController
System.Web.Http.Controllers: HttpControllerDescriptor;CreateController;Loyalty.Services.WebApi.Controllers.EntityInstanceController
System.Web.Http.Controllers: EntityInstanceController;ExecuteAsync;:
System.Web.Http.Action: ApiControllerActionSelector;SelectAction;:
System.Web.Http.Action: ApiControllerActionSelector;SelectAction;Selected action 'Get(String entityDefinitionName)'
System.Net.Http.Formatting: DefaultContentNegotiator;Negotiate;Type='HttpError', formatters=[JsonMediaTypeFormatterTracer, XmlMediaTypeFormatterTracer, FormUrlEncodedMediaTypeFormatterTracer, FormUrlEncodedMediaTypeFormatterTracer]
System.Net.Http.Formatting: JsonMediaTypeFormatter;GetPerRequestFormatterInstance;Obtaining formatter of type 'JsonMediaTypeFormatter' for type='HttpError', mediaType='application/json; charset=utf-8'
System.Net.Http.Formatting: JsonMediaTypeFormatter;GetPerRequestFormatterInstance;Will use same 'JsonMediaTypeFormatter' formatter
System.Net.Http.Formatting: DefaultContentNegotiator;Negotiate;Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'
System.Web.Http.Controllers: EntityInstanceController;ExecuteAsync;:
System.Net.Http.Formatting: JsonMediaTypeFormatter;WriteToStreamAsync;Value='System.Web.Http.HttpError', type='HttpError', content-type='application/json; charset=utf-8'
System.Net.Http.Formatting: JsonMediaTypeFormatter;WriteToStreamAsync;:
System.Web.Http.Request: ;;Content-type='application/json; charset=utf-8', content-length=68
System.Web.Http.Controllers: EntityInstanceController;Dispose;:
System.Web.Http.Controllers: EntityInstanceController;Dispose;:
Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationMiddleware Information: 0 : : OAUTH: Applying Challange...
A first chance exception of type 'System.Web.HttpException' occurred in System.Web.dll
所看到的情况是,中间件的响应处理部分遵循俄罗斯套娃模型试图修改标头,但响应已经在之前的阶段完成。我尝试添加不同的阶段标记来控制此行为,但似乎没有任何帮助。
看到这个跟踪后令人惊讶的是,并不是每次都发生。我使用更小型的自己编写的版本的中间件,在注册此中间件取代MS的位置后,确实开始在每个请求上看到错误。我想知道它是否总是被抛出,但偶尔会被忽略,或者Fiddler没有等待足够长的时间才能看到它。
我目前最好的猜测是,由于在Owin和WebApi设置中使用了不同的HttpConfiguration,因此导致了这个问题。不幸的是,由于委托处理程序在OWIN中在不同的上下文中运行,您无法访问路由数据,因此无法完全交换HTTPApplication并转向OWIN,否则将破坏我们现有基础架构中的很多内容。
是否有人可以给我一些指针,说明这里发生了什么情况? 这是受支持的场景吗? 我是否忽略了一些明显的东西?