LoginSignup
2
2

More than 5 years have passed since last update.

意外と知られてない気がするOwin+ASP.NET(IIS) のパイプラインの実行順序

Last updated at Posted at 2015-06-09

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の間に割り込む。

参考

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2