2012年10月17日 星期三

系統Memo - IHttpModule 中使用Session State

這個問題其實挺弔詭的,沒有什麼文件清楚的寫出來(該死的微軟)
要在IHttpModule中使用Session有非常多的限制:

1. 網路上眾說紛紜,有人說只在AcquireRequestState和PreRequestHandlerExecute兩個事件中,才有辦法使用Session,但也有人說http module根本沒辦法使用session,造成不少困擾。

2. 經測試,即使是在上述兩個事件中,HttpApplication.Context.Session依然為null,我的猜測是這樣的方法只適用於.aspx之類的http request,其餘一律行不通。(我發的http request是抓.png或是manifest這類的行為)

最後採用的解法是:
http://forums.asp.net/t/1098574.aspx/1

我看不太懂裡面針對handler物件繞來繞去的原因是什麼,只大概猜說是要自己宣告一個Handler類別,產生handler物件,然後用原本的Application.Context.Handler傳進來,藉此啟動SessionStateModule,讓SessionState成為avaliable狀態。

以下只擷取相關部分,RequestBegin之類的事件省略,
Code snippet:


public void Init(HttpApplication application)
{
    // following two event handler are both required
    application.PostAcquireRequestState += new EventHandler(OnPostAcquireRequestState);
    application.PostMapRequestHandler += new EventHandler(OnPostMapRequestHandler);
}


/**
* for the usage of SessionState, replace the original handler with ours, force SessionState to be valiable
**/
public void OnPostMapRequestHandler(Object sender, EventArgs e)
{
    HttpApplication application = (HttpApplication)sender;

    if (application.Context.Handler is IReadOnlySessionState || application.Context.Handler is IRequiresSessionState)
    {
        // no need to replace the original handler
        return;
    }

    // swap the original handler
    application.Context.Handler = new TempHandler(application.Context.Handler);
}


public void OnPostAcquireRequestState(Object sender, EventArgs e)
{
    HttpApplication application = (HttpApplication)sender;
    TempHandler handler = HttpContext.Current.Handler as TempHandler;

     if (handler != null)
     {
         HttpContext.Current.Handler = handler.myHandler;
     }

    // from this moment, SessionState is valiable
    HttpSessionState session = application.Context.Session;

}


/**
* A temp handler used to force the SessionStateModule to load session state
**/
public class TempHandler : IHttpHandler, IRequiresSessionState
{
    internal readonly IHttpHandler myHandler; // store original application context handler

    public TempHandler(IHttpHandler originalhttpHandler)
    {
        this.myHandler = originalhttpHandler;
    }

    public void ProcessRequest(HttpContext context)
    {
        throw new InvalidOperationException("InvalidOperationException");
    }

    public bool IsReusable
    {
        get { return false; }
    }
}

另外,module類別除了繼承IHttpModule以外,必須再繼承IRequiresSessionState。

Anyway,這個方法讓我成功取到Session.SessionID,原理之後再慢慢思考。


2012年10月16日 星期二

系統Memo - IIS Server網站掛載HTTP Module

1. 將C#程式編譯成.dll檔,放置在網站目錄下bin資料夾,與web.config層級相同。
2. web.config設定方式如下:
< configuration > 
< system.web >
< customErrors mode="Off" />
< /system.web >
< system.webServer >
< modules >
< add type="NameSpace.ModuleName" name="NameSpace" />
< /modules >
< /system.webServer >
< /configuration >

3. 採用介面為IHttpModules。

系統Memo - IIS Server 掛載網路位置的磁碟機 Update

承上一篇筆記,
去改AppPool的設定,使得.NET Framework的版本與DefaultAppPool不一樣,
可能導致之後無法在這個應用程式上掛任何.NET程式。

後來嘗試了另一種方法,其實很直觀,
只是當初沒想到。
1. 一樣新建立一個應用程式,使用DefaultAppPool的設定即可。
2. 注意上一篇講到的帳號密碼部分,這會影響到存取權限。
3. 在應用程式下建立新的虛擬目錄,將路徑指向目標網路磁碟機。

這樣就可以讓.NET程式運作正常,也可以讓程式和網站儲存內容分開。



2012年10月2日 星期二

系統Memo - IIS Server 掛載網路位置的磁碟機

紀錄一下,
這個問題困擾了我兩天,連公司的MIS都覺得莫名其妙,結果看了這篇網誌瞬間解決!

http://maxtellyou.blogspot.tw/2010/02/iis-7.html

大致上有幾點:
1. 在設定實體路徑時必須使用"//磁碟機網路位址/xxx",不能設定為"磁碟機代號:\xxx",因為IIS只支援UNC路徑而不支援網路磁碟機路徑。
2. 雖然說是要在預設網站(Default Web Site)下建立虛擬目錄,但其實是建立一個新的應用程式(Application),並搭配新建立的應用程式集區(ApplicationPool)。
3. 新建立的應用程式集區必須設定為"沒有Managed程式碼"。
4. 在IIS server上必須要有一個與網路磁碟機一模一樣帳號密碼的使用者帳戶,比如說網路磁碟機上開的存取帳號為 testUser / 1234,那麼IIS server上也要有一個帳號 testUser / 1234,只要存在就好,IIS端不一定要用此帳號操作。
5. IIS端建立的新應用程式需設定連線身分為此組帳號密碼,登入類型為clearText即可。