這個問題其實挺弔詭的,沒有什麼文件清楚的寫出來(該死的微軟)
要在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月17日 星期三
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。
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程式運作正常,也可以讓程式和網站儲存內容分開。
去改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即可。
這個問題困擾了我兩天,連公司的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即可。
訂閱:
文章 (Atom)