We are using Owin middleware in an ASP.NET Web API 2 project hosted in IIS.
I am currently experiencing a strange phenomenon where the IOwinContext.Response.Body is not being written to, and actually, even when I have a break point set in the middleware after awake Next.Invoke(), and it gets hit, the response has already been sent back to the server even if I haven't continued yet.
When I look at the response body on the IOwinContext it is empty. However, I can get the response from the HttpContext.Response.Filter. When I use the HttpContext and hit the break point, then the response isn't sent back until I continue. Below is the current configuration method being used in our Startup.cs class.
public async void Configuration(IAppBuilder app)
{
try
{
// Global Config
var config = GlobalConfiguration.Configuration;
// configure dependency injection
UnityConfig.RegisterComponents();
// configure log for net
log4net.Config.XmlConfigurator.Configure();
// turn around all requests right here
app.Use(async (context, next) =>
{
if (context.Request.Path.ToString() == "/")
{
string text = "UP";
context.Response.StatusCode = 200;
context.Response.ReasonPhrase = text;
await context.Response.WriteAsync(text);
return;
}
await next.Invoke();
});
// Handle exceptions in the OWIN layer here
app.UseUncaughtExceptionHandler();
// add cors headers
app.Use(async (context, next) => { });
// some UI stuff
app.Use(async (context, next) => { });
// Log Request Metrics
app.UseLogRequestMetrics();
// Evaluate Partner Key
app.MapWhen(context => Regex.IsMatch(context.Request.Uri.PathAndQuery.ToLower(), @"/api"), newApp =>
{
#if !DEBUG
newApp.Use<Middleware1>();
#endif
newApp.Use<Middleware2>();
newApp.Use<Middleware3>(); // On the response path back, the IOwinResponse body is already empty
});
WebApiConfig.Register(config);
app.UseWebApi(config); // It seems like I'm losing the response in here, but I don't really know
config.EnsureInitialized();
// Configure object mapping
AutoMapperConfig.Configure();
}
catch (Exception ex)
{
await LogForNetErrorLogger.LogError(ex);
}
}
I'm pretty sure my middleware is messed up, but the response is already gone before it gets back to the first of my middlewares (Middleware3) after the await Next.Invoke()
Any insight or thought provoking would be appreciated. Also, if this isn't enough information please let me know.
So, as in my post above, the problem, I thought, was the HttpResponse was being sent back before the IOwinResponse was. As it turns out, I completely overlooked the mapping section:
app.MapWhen(context => Regex.IsMatch(context.Request.Uri.PathAndQuery.ToLower(), @"/api"), newApp =>
{
#if !DEBUG
newApp.Use<Middleware1>();
#endif
newApp.Use<Middleware2>();
newApp.Use<Middleware3>();
});
When you use app.Map()
it branches the middleware. So, if the path matched "/api" it would branch. However, it was also still using the app.UseWebApi()
component so that was why I had two different responses and why the response I was expecting wasn't written to the Middleware3
component's IOwinContext
. I fixed it by removing the app.MapWhen()
method, changing it from this:
app.MapWhen(context => Regex.IsMatch(context.Request.Uri.PathAndQuery.ToLower(), @"/site"), newApp =>
{
#if !DEBUG
newApp.Use<Middleware1>();
#endif
newApp.Use<Middleware2>();
newApp.Use<Middleware3>(); // On the response path back, the IOwinResponse body is already empty
});
to this:
#if !DEBUG
newApp.Use<Middleware1>();
#endif
newApp.Use<Middleware2>();
newApp.Use<Middleware3>();
and putting this piece of code at the beginning of the middleware components Middleware1
, Middleware2
, Middleware3
:
public override async Task Invoke(IOwinContext context)
{
if (!context.Request.Path.ToString().StartsWith("/api/"))
{
await Next.Invoke(context);
return;
}
// stuff I want to run if the above doesn't match
await Next.Invoke(context);
...
}
Well, at least the fix was simple, even if it took me three weeks to find it. If you want to read up on the IAppBuilder.MapWhen extension method, here is some documentation https://msdn.microsoft.com/en-us/library/owin.mapwhenextensions.mapwhen(v=vs.113).aspx .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.