OwinのUseStageMarkerが何を行ってるのか、コードを追いかけても全然わからなかったので、実行順序をキャプチャして、やっと理解することができたので紹介します。
※今回の検証はWebAPIでやりました。
準備
Global.axax.cs
//以下を追加
protected void Application_BeginRequest(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_BeginRequest event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_AuthenticateRequest event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_AuthorizeRequest event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_ResolveRequestCache(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_ResolveRequestCache event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Session_Start(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Session_Start event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_AcquireRequestState event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_PreRequestHandlerExecute event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_PostRequestHandlerExecute(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_PreRequestHandlerExecute event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_ReleaseRequestState(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_ReleaseRequestState event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_UpdateRequestCache(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_UpdateRequestCache event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_EndRequest(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_EndRequest event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_PreSendRequestHandlers(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_PreSendRequestHandlers event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
protected void Application_PreSendRequestContent(object sender, EventArgs e)
{
Trace.WriteLine("HttpApplication Application_PreSendRequestContent event, Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
Startup.cs
//以下のように編集
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "First!");
return next.Invoke();
});
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "Authenticate");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.Authenticate);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "PostAuthenticate");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.PostAuthenticate);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "Authorize");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.Authorize);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "PostAuthorize");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.PostAuthorize);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "ResolveCache");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.ResolveCache);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "PostResolveCache");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.PostResolveCache);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "MapHandler");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.MapHandler);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "PostMapHandler");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.PostMapHandler);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "AcquireState");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.AcquireState);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "PostAcquireState");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.PostAcquireState);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "PreHandlerExecute");
return next.Invoke();
});
//app.UseStageMarker(PipelineStage.PreHandlerExecute);
app.Use((context, next) =>
{
PrintCurrentIntegratedPipelineStage(context, "2nd Use");
return next.Invoke();
});
app.Run(context =>
{
PrintCurrentIntegratedPipelineStage(context, "Content Reposnse");
return context.Response.WriteAsync("Hello world");
});
}
private void PrintCurrentIntegratedPipelineStage(IOwinContext context, string msg)
{
var currentIntegratedpipelineStage = HttpContext.Current.CurrentNotification;
var trace = context.Get<TextWriter>("host.TraceOutput");
trace.WriteLine("OWIN event: " + currentIntegratedpipelineStage + " Msg: " + msg + ",Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
MyModule1.cs
//新規で作る
public class MyModule1 : IHttpModule
{
private string _moduleName;
public void Init(HttpApplication context)
{
var nameProp = context.GetType().GetProperty("CurrentModuleCollectionKey", BindingFlags.NonPublic | BindingFlags.Instance);
_moduleName = (string)nameProp.GetValue(context, null);
context.BeginRequest += (sender, args) => PrintCurrentIntegratedPipelineStage("BeginRequest");
context.AuthenticateRequest += (sender, args) => PrintCurrentIntegratedPipelineStage("AuthenticateRequest");
context.AuthorizeRequest += (sender, args) => PrintCurrentIntegratedPipelineStage("AuthorizeRequest");
context.ResolveRequestCache += (sender, args) => PrintCurrentIntegratedPipelineStage("ResolveRequestCache");
context.AcquireRequestState += (sender, args) => PrintCurrentIntegratedPipelineStage("AcquireRequestState");
context.PreRequestHandlerExecute += (sender, args) => PrintCurrentIntegratedPipelineStage("PreRequestHandlerExecute");
context.PostRequestHandlerExecute += (sender, args) => PrintCurrentIntegratedPipelineStage("PostRequestHandlerExecute");
context.ReleaseRequestState += (sender, args) => PrintCurrentIntegratedPipelineStage("ReleaseRequestState");
context.UpdateRequestCache += (sender, args) => PrintCurrentIntegratedPipelineStage("UpdateRequestCache");
context.EndRequest += (sender, args) => PrintCurrentIntegratedPipelineStage("EndRequest");
}
private void PrintCurrentIntegratedPipelineStage(string msg)
{
var currentIntegratedpipelineStage = HttpContext.Current.CurrentNotification;
Trace.WriteLine(_moduleName + "1 IIS event: " + currentIntegratedpipelineStage + " Msg: " + msg + ",Thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
public void Dispose()
{
}
}
Web.config
<system.webServer>
<!-- 追加 -->
<modules>
<add name="HttpModule1" type="WebApplication1.MyModule1"/>
<add name="HttpModule2" type="WebApplication1.MyModule1"/>
<add name="HttpModule3" type="WebApplication1.MyModule1"/>
</modules>
</system.webServer>
検証
※初回リクエスト時は内容変わるので2回目のリクエストをキャプチャしています。
実行結果.
HttpModule11 IIS event: BeginRequest Msg: BeginRequest,Thread:6
HttpModule21 IIS event: BeginRequest Msg: BeginRequest,Thread:6
HttpModule31 IIS event: BeginRequest Msg: BeginRequest,Thread:6
HttpApplication Application_BeginRequest event, Thread:6
HttpModule11 IIS event: AuthenticateRequest Msg: AuthenticateRequest,Thread:6
HttpModule21 IIS event: AuthenticateRequest Msg: AuthenticateRequest,Thread:6
HttpModule31 IIS event: AuthenticateRequest Msg: AuthenticateRequest,Thread:6
HttpApplication Application_AuthenticateRequest event, Thread:6
HttpModule11 IIS event: AuthorizeRequest Msg: AuthorizeRequest,Thread:6
HttpModule21 IIS event: AuthorizeRequest Msg: AuthorizeRequest,Thread:6
HttpModule31 IIS event: AuthorizeRequest Msg: AuthorizeRequest,Thread:6
HttpApplication Application_AuthorizeRequest event, Thread:6
HttpModule11 IIS event: ResolveRequestCache Msg: ResolveRequestCache,Thread:6
HttpModule21 IIS event: ResolveRequestCache Msg: ResolveRequestCache,Thread:6
HttpModule31 IIS event: ResolveRequestCache Msg: ResolveRequestCache,Thread:6
HttpApplication Application_ResolveRequestCache event, Thread:6
HttpModule11 IIS event: AcquireRequestState Msg: AcquireRequestState,Thread:6
HttpModule21 IIS event: AcquireRequestState Msg: AcquireRequestState,Thread:6
HttpModule31 IIS event: AcquireRequestState Msg: AcquireRequestState,Thread:6
HttpApplication Application_AcquireRequestState event, Thread:6
HttpModule11 IIS event: PreExecuteRequestHandler Msg: PreRequestHandlerExecute,Thread:6
HttpModule21 IIS event: PreExecuteRequestHandler Msg: PreRequestHandlerExecute,Thread:6
HttpModule31 IIS event: PreExecuteRequestHandler Msg: PreRequestHandlerExecute,Thread:6
OWIN event: PreExecuteRequestHandler Msg: First!,Thread:6
OWIN event: PreExecuteRequestHandler Msg: Authenticate,Thread:6
OWIN event: PreExecuteRequestHandler Msg: PostAuthenticate,Thread:6
OWIN event: PreExecuteRequestHandler Msg: Authorize,Thread:6
OWIN event: PreExecuteRequestHandler Msg: PostAuthorize,Thread:6
OWIN event: PreExecuteRequestHandler Msg: ResolveCache,Thread:6
OWIN event: PreExecuteRequestHandler Msg: PostResolveCache,Thread:6
OWIN event: PreExecuteRequestHandler Msg: MapHandler,Thread:6
OWIN event: PreExecuteRequestHandler Msg: PostMapHandler,Thread:6
OWIN event: PreExecuteRequestHandler Msg: AcquireState,Thread:6
OWIN event: PreExecuteRequestHandler Msg: PostAcquireState,Thread:6
OWIN event: PreExecuteRequestHandler Msg: PreHandlerExecute,Thread:6
OWIN event: PreExecuteRequestHandler Msg: 2nd Use,Thread:6
OWIN event: PreExecuteRequestHandler Msg: Content Reposnse,Thread:6
HttpModule11 IIS event: EndRequest Msg: EndRequest,Thread:7
HttpModule21 IIS event: EndRequest Msg: EndRequest,Thread:7
HttpModule31 IIS event: EndRequest Msg: EndRequest,Thread:7
HttpApplication Application_EndRequest event, Thread:7
HttpApplication Application_PreSendRequestContent event, Thread:7
ここで、Startup.csのコメントアウト(app.UseStageMarker)を外してもう一度実行すると
実行結果.
HttpModule11 IIS event: BeginRequest Msg: BeginRequest,Thread:7
HttpModule21 IIS event: BeginRequest Msg: BeginRequest,Thread:7
HttpModule31 IIS event: BeginRequest Msg: BeginRequest,Thread:7
HttpApplication Application_BeginRequest event, Thread:7
HttpModule11 IIS event: AuthenticateRequest Msg: AuthenticateRequest,Thread:7
HttpModule21 IIS event: AuthenticateRequest Msg: AuthenticateRequest,Thread:7
HttpModule31 IIS event: AuthenticateRequest Msg: AuthenticateRequest,Thread:7
OWIN event: AuthenticateRequest Msg: First!,Thread:7
OWIN event: AuthenticateRequest Msg: Authenticate,Thread:7
HttpApplication Application_AuthenticateRequest event, Thread:7
OWIN event: AuthenticateRequest Msg: PostAuthenticate,Thread:7
HttpModule11 IIS event: AuthorizeRequest Msg: AuthorizeRequest,Thread:7
HttpModule21 IIS event: AuthorizeRequest Msg: AuthorizeRequest,Thread:7
HttpModule31 IIS event: AuthorizeRequest Msg: AuthorizeRequest,Thread:7
OWIN event: AuthorizeRequest Msg: Authorize,Thread:7
HttpApplication Application_AuthorizeRequest event, Thread:7
OWIN event: AuthorizeRequest Msg: PostAuthorize,Thread:7
HttpModule11 IIS event: ResolveRequestCache Msg: ResolveRequestCache,Thread:7
HttpModule21 IIS event: ResolveRequestCache Msg: ResolveRequestCache,Thread:7
HttpModule31 IIS event: ResolveRequestCache Msg: ResolveRequestCache,Thread:7
OWIN event: ResolveRequestCache Msg: ResolveCache,Thread:7
HttpApplication Application_ResolveRequestCache event, Thread:7
OWIN event: ResolveRequestCache Msg: PostResolveCache,Thread:7
OWIN event: MapRequestHandler Msg: MapHandler,Thread:7
OWIN event: MapRequestHandler Msg: PostMapHandler,Thread:7
HttpModule11 IIS event: AcquireRequestState Msg: AcquireRequestState,Thread:7
HttpModule21 IIS event: AcquireRequestState Msg: AcquireRequestState,Thread:7
HttpModule31 IIS event: AcquireRequestState Msg: AcquireRequestState,Thread:7
OWIN event: AcquireRequestState Msg: AcquireState,Thread:7
HttpApplication Application_AcquireRequestState event, Thread:7
OWIN event: AcquireRequestState Msg: PostAcquireState,Thread:7
HttpModule11 IIS event: PreExecuteRequestHandler Msg: PreRequestHandlerExecute,Thread:7
HttpModule21 IIS event: PreExecuteRequestHandler Msg: PreRequestHandlerExecute,Thread:7
HttpModule31 IIS event: PreExecuteRequestHandler Msg: PreRequestHandlerExecute,Thread:7
OWIN event: PreExecuteRequestHandler Msg: PreHandlerExecute,Thread:7
OWIN event: PreExecuteRequestHandler Msg: 2nd Use,Thread:7
OWIN event: PreExecuteRequestHandler Msg: Content Reposnse,Thread:7
HttpModule11 IIS event: EndRequest Msg: EndRequest,Thread:25
HttpModule21 IIS event: EndRequest Msg: EndRequest,Thread:25
HttpModule31 IIS event: EndRequest Msg: EndRequest,Thread:25
HttpApplication Application_EndRequest event, Thread:25
HttpApplication Application_PreSendRequestContent event, Thread:25
まとめ
・Owinの場合、PreExecuteRequestHandlerとEndRequestの間に割り込み、ここでパイプラインを構築することができる。
・ここで、UseStageMarkerによって割り込みタイミングを(ある程度)コントロールできる。
・UserStageMakerを使うと、HttpModuleとHttpApplicationの間に割り込む。