顯示具有 asp.net 標籤的文章。 顯示所有文章
顯示具有 asp.net 標籤的文章。 顯示所有文章

星期二, 八月 05, 2008

Asp.Net的TreeView Checked事件 Part II

Asp.Net的TreeView Checked事件裏,MIS小姐希望能夠自動選取子節點,但後來又希望能做更多的動作,因此只好強迫TreeView postback。
在aspx加上
<script language="javascript" type="text/javascript">
    function TreeNodeChecked()  {  
          var ele = window.event.srcElement;  
          if(ele.type=='checkbox')  
          {  
              var form1 = document.getElementById('form1');
              form1.submit();         
         }  
    }
</script>
在aspx.cs的Page_Load事件再加上
protected void Page_Load(object sender, EventArgs e)
{
   TreeView1.Attributes.Add("onclick", "TreeNodeChecked();");
}

星期六, 七月 19, 2008

Asp.Net的TreeView Checked事件

美麗的MIS小姐希望在asp.net的TreeView點選節點時,會自動選取子節點,但TreeView為了不讓畫面一直閃動,所以沒有支援Node裏CheckBox的AutoPostBack。 這種時候,身為閒人的鳥毅當然要幫事務繁忙的MIS小姐找solution,對岸的高手早利用JavaScript與asp.net的Attribute做出來,參考:asp.net TreeView 一些操作

簡單描述一下:在aspx加上

<script language="javascript" type="text/javascript">
function TreeNodeChecked() {
var ele = window.event.srcElement;
if(ele.type=='checkbox')
{
var childrenDivID = ele.id.replace('CheckBox','Nodes');
var div = document.getElementById(childrenDivID);
if(div==null)return;
var checkBoxs = div.getElementsByTagName('INPUT');
for(var i=0;i<checkBoxs.length;i++)
{
if(checkBoxs[i].type=='checkbox')
checkBoxs[i].checked=ele.checked;
}
}
}
}
</script>
在aspx.cs的Page_Load修改為

protected void Page_Load(object sender, EventArgs e)
{
TreeView1.Attributes.Add("onclick", "TreeNodeChecked();");
}


最後,為拉抬人氣,附上美麗的MIS小姐倩影:

星期五, 七月 11, 2008

當FCKeditor.Net遇上Ajax.asp.net

原本使用FCKeditor.Net這個Open Source的Rich Text Editor一段時間,但是網頁加上Ajax.asp.net的Update Panel時,FCKeditor.Net就會發生問題。

幸好國外高手已找出解決之道:Easy way to get FCKEditor to work inside an ASP.Net AJAX UpdatePanel,希望下一版本的FCKeditor.Net直接相容Update Panel呀!

星期三, 三月 26, 2008

動態改變RDLC報表DataSource

先用設定好的DataSet(這裏叫Report.xsd)設定RDLC檔,以Report.rdlc為例。
接者在Asp.Net報表裏拉入Report Viewer,指向Report.rdlc,刪掉datasource那些用不到的東西,在aspx裏會看到類似
<rsweb:reportviewer id="ReportViewer1" runat="server" font-names="Verdana" font-size="8pt" height="400px" width="800px">
<LocalReport ReportPath="Report.rdlc">
</LocalReport>
</rsweb:reportviewer>

RDLC檔其實是一個xml,和Crystal Reports的rpt二進位格式大不同。用文字編輯器打開來看,會看到類似:<DataSet Name="Report_ReportList"> 或是<DataSet Name>Report_ReportList</DataSet Name> 這裏Report是我在.xsd檔裏定義的DataSet名稱,而ReportList是table名稱,知道這個DataSet Name後,就可以動態改變RDLC的DataSource。

用我寫的程式片斷舉例:
private void RefreshReport()
{
ReportViewer1.LocalReport.DataSources.Clear();
DataTable dt = getReportDataTable(); //這是我寫的private method
ReportViewer1.LocalReport.DataSources.Add(
new Microsoft.Reporting.WebForms.ReportDataSource("Report_ReportList", dt));
}
很簡單吧!只要加入一個ReportDataSource,參數裏設定DataSet為相同名稱,再把DataTable傳入即可。要重新改變報表內容時,必須先執行
ReportViewer1.LocalReport.DataSources.Clear(); 
否則每次都只看到第一次傳入的內容。

星期一, 三月 24, 2008

用ZedGraph畫統計圖

才剛貼完上一篇,馬上就有位朋友丟過來一個LGPL Open Source元件的網址:ZedGraph

參考:A flexible charting library for .NET

基本上,照著Use RenderMode.RawImage in a web page,應該可以做出來,只要注意把ZedGraph.dll和ZedGraph.Web.dll都複製到bin下即可。我是偷懶直接下載zedgraph_web_sample_v5.1.2.zip,用檔案系統網站開啟,再把那2個dll丟到bin下測試。



範例裏有三個目錄,我們只關注ImageTagCS和RawModeCS。原來以為ImageTagCS做成WebControl,只要一個檔案即時render比較好,但我發現錯了:會不斷產生暫存影像檔。
所以比較好的做法與ProEssentials一樣,必須用另一支aspx產生影像,也就是RawModeCS裏的做法。

重頭來做一次好了,先開一個新的Asp.Net檔案系統網站,再開bin目錄,將ZedGraph.dll和ZedGraph.Web.dll都複製到bin下。

接著加入一個新WebForm,叫zedgraph.aspx


在Default.aspx裏拉進一個button和一個Image物件,在button上double click,在form標籤內應該是
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="查詢" />
<asp:Image ID="Image1" runat="server" ImageUrl="zedgraph.aspx" />


在Default.aspx.cs裏
protected void Button1_Click(object sender, EventArgs e)
{
PointPairList list1 = new PointPairList();
PointPairList list2 = new PointPairList();
PointPairList list3 = new PointPairList();
Random rand = new Random();

for ( double x=0; x<5; x+=1.0 )
{
double y = rand.NextDouble() * 1000;
double y2 = rand.NextDouble() * 1000;
double y3 = rand.NextDouble() * 1000;
list.Add( x, y );
list2.Add( x, y2 );
list3.Add( x, y3 );
}
}

打開zedgraph.aspx,刪除原有內容,輸入
<%@ Page Language="c#" Inherits="ZG1.zedgraph" CodeFile="zedgraph.aspx.cs" %>
<%@ Register TagPrefix="zgw" Namespace="ZedGraph.Web" Assembly="ZedGraph.Web" %>
<zgw:zedgraphweb id="ZedGraphWeb1" runat="server" width="800" height="450" rendermode="RawImage" onrendergraph="OnRenderGraph"></zgw:zedgraphweb>

在zedgraph.aspx.cs裏加入

protected void OnRenderGraph(ZedGraphWeb zgw, Graphics g, MasterPane masterPane)
{
// Get the GraphPane so we can work with it
GraphPane myPane = masterPane[0];
myPane.Title.Text = "電腦統計圖";
myPane.XAxis.Title.Text = "部門";
myPane.YAxis.Title.Text = "台數";
// 這裏可視情況改成由DataTable讀入資料,
// 將DataTable從前一頁利用Session傳入
PointPairList list1 = (PointPairList)Session["list1"];
PointPairList list2 = (PointPairList)Session["list2"];
PointPairList list3 = (PointPairList)Session["list3"];

BarItem myCurve = myPane.AddBar("桌機", list1, Color.Blue);
myCurve.Bar.Fill = new Fill(Color.Blue, Color.White, Color.Blue);
BarItem myCurve2 = myPane.AddBar("筆電", list2, Color.Red);
myCurve2.Bar.Fill = new Fill(Color.Red, Color.White, Color.Red);
BarItem myCurve3 = myPane.AddBar("印表機", list3, Color.Green);
myCurve3.Bar.Fill = new Fill(Color.Green, Color.White, Color.Green);

myPane.XAxis.MajorTic.IsBetweenLabels = true;
string[] labels = { "行政部", "會計部", "資訊部", "業務部", "研發部" };
myPane.XAxis.Scale.TextLabels = labels;
myPane.XAxis.Type = AxisType.Text;
myPane.Fill = new Fill(Color.White, Color.FromArgb(200, 200, 255), 45.0f);
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);

masterPane.AxisChange(g);
//產生每個Bar上的數量(Label),原範例沒有喲
BarItem.CreateBarLabels(myPane, false, "f0");
}

再執行 Default.aspx,執行結果:


重點在於把值利用Session傳入,以及zedgraph的事件


如果像鳥毅一樣運氣太好,遇到browser cache圖怎麼辦?尤其是放在UpdatePanel內更容易發生,最簡單的方法就是在每次查詢(button click)事件內加上一條:
Image1.ImageUrl = "zedgraph.aspx?xxx="+DateTime.Now.Millisecond;
這樣應該就沒問題了。

利用OWC畫統計圖

VB超人告訴我,可以用Microsoft Office Web Components(OWC)畫統計圖,比起其他的Asp.net統計圖,又多了些互動功能(在用戶端有裝Office的情況)。

下載:Office 2003 增益集:Office 網頁元件
參考:
The Microsoft Office Web Components
ASP.NET Server-Side Charting with OWC11

在Asp.Net 2.0的開發模式中,只要放在bin下就算加入參考,所以鳥毅先開一個檔案系統的網站


再把從codeproject下載的專案裏的bin目錄複製過來,省得自己找dll檔,在專案總管按下重新整理即可


把Alvin Bruney寫的這段Code複製到Page_Load,變成
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. //First create a ChartSpace object to hold the chart
  4. ChartSpace objCSpace = new ChartSpaceClass();
  5. //Add a chart and provide a type
  6. ChChart objChart = objCSpace.Charts.Add(0);
  7. objChart.Type = ChartChartTypeEnum.chChartTypePie3D;
  8. //add chart titles and legend
  9. objChart.HasTitle = true;
  10. objChart.Title.Caption = "ASP.NET Charts";
  11. objChart.HasLegend = true;
  12. objChart.Legend.Border.DashStyle = OWC11.ChartLineDashStyleEnum.chLineDash;
  13. objChart.Legend.Position = OWC11.ChartLegendPositionEnum.chLegendPositionRight;
  14. //Populate with contrived data
  15. string strCategory = "Cars, Trucks, Vans, Big Rigs, Motorcycles, Mopeds";
  16. string strValue = "13,12,31,43,23,15";
  17. //Add a series to the chart's series collection
  18. objChart.SeriesCollection.Add(0);
  19. //load the category and value data
  20. objChart.SeriesCollection[0].SetData(ChartDimensionsEnum.chDimCategories,
  21. (int)ChartSpecialDataSourcesEnum.chDataLiteral, strCategory);
  22. objChart.SeriesCollection[0].SetData(ChartDimensionsEnum.chDimValues,
  23. (int)ChartSpecialDataSourcesEnum.chDataLiteral, strValue);
  24. //show the chart on the client
  25. Response.ContentType = "image/gif";
  26. Response.BinaryWrite((byte[])objCSpace.GetPicture("gif", 500, 400));
  27. Response.End();
  28. }

執行後結果:


詳細的物件模型請參考:HOW TO:尋找 Office Web 元件 (OWC) 程式設計說明文件與範例

說真的,這種COM物件的繪圖方式類似ProEssentials得一個個指定,我還是比較喜歡原生支援.Net的Crystal Reports

星期五, 三月 21, 2008

Free Chart controls for ASP.NET

電腦管理程式的承辦人說希望能有長條圖,因此找了一下幾個免費的元件:
不過說實話,如果沒有太特別的需求,內建的Crystal Reports就很好用,這個東西好像放在Server上要另外買。統計圖最有名的元件應該是Proessentials,我有下載試用一下,沒有像Crystal Reports和.Net整合的那麼好,而且一定要6.0版後才有支援UTF-8字元,敝公司已經買的5.0版就很可惜不能用(標題有堃會亂碼,好死不死敝公司有人的名字裏就有堃)。最後值得一試的是微軟自己的RDLC報表,雖然功能比不上Crystal Reports,但我的需求足夠了,而且預期會愈來愈強,應該就用RDLC了吧。

參考:
Visual Studio 2008-初窺Report Viewer 2008
ASP.NET中动态控制RDLC报表
RDLC报表使用

星期二, 三月 04, 2008

GridView合併儲存格

修改自 藍色小鋪 豬豬泰芮陳 關於 GridView的合併儲存格這裏有類似的程式,但我覺得豬豬泰芮陳寫得比較好。我改成多欄位合併,其餘沒動。
[Asp.Net]GridView中根据前后列之间的关联关系合并单元格有更進階的做法,但不是我要的。

protected void GridView1_PreRender(object sender, EventArgs e)
{
int[] mergeColumns = { 0, 1, 3, 4 }; //要合併的欄位
foreach (int mergeColumn in mergeColumns)
{
int i = 1;
foreach (GridViewRow wkItem in GridView1.Rows)
{
if (wkItem.RowIndex != 0)
{
if (wkItem.Cells[mergeColumn].Text.Trim() == GridView1.Rows[(wkItem.RowIndex - i)].Cells[mergeColumn].Text.Trim())
{
GridView1.Rows[(wkItem.RowIndex - i)].Cells[mergeColumn].RowSpan += 1;
wkItem.Cells[mergeColumn].Visible = false;
i = i + 1;
}
else
{
GridView1.Rows[(wkItem.RowIndex)].Cells[mergeColumn].RowSpan += 1;
i = 1;
}
}
else
{
wkItem.Cells[mergeColumn].RowSpan = 1;
}
}
}

星期三, 一月 30, 2008

開源基於C#的CMS

朋友看到鳥毅的求救文,介紹mojoPortalumbraco這兩個CMS。

umbraco比較炫,幾乎所有的動作都是AJAX。若從source編譯時發生錯誤,得設定編碼為無BOM的utf-8。自行編譯很快,可惜我跑起來不是很正常,而且在IIS安裝失敗就懶得再測。

mojoPortal雖然專案多,但編譯速度也很快,而且也沒有警告,NTLM整合只要在web.config設定authentication="windows",完全不需要另外設定。目前看到的缺點是模組過少,優點則是編譯和執行速度都很快,又支援Mono和多種Database,未來應該頗有發展性。目前有vs2005和vs2008的solution,算是在下接觸到的CMS動作最快的一個。

以上兩個CMS皆有商業版本,而且持續在開發中,open source還是得需要商業化的支持才能長久呀~

星期五, 一月 18, 2008

Rainbow Portal 2.0 NTLM 網域整合Hack (續)

照著Rainbow Portal 2.0 NTLM 網域整合Hack修改後,遇到要利用AD群組時,找不到舊版選擇Windows 群組的選項。

在MSDN上ADSI的範例,.Net 1.1和.Net 2.0/3.5也略有不同,而我測試結果是.Net 2.0版本才可正常運行。我自己的情況是在Projects\Rainbow.Framework.Core\Helpers\ADHelper.cs裏的 public static string[] GetUserGroups(string UserAccount) 沒有傳回group資料,因此這裏利用MSDN的範例寫一個簡易版,若能正確執行就不必自己改。public static ArrayList getUserGroups(string userid) // userid是去掉DOMAIN的user account
{
string path = Config.ADdns;
ArrayList ret = new ArrayList();
ret.Add("Authenticated Users");
ret.Add("All Users");
DirectoryEntry entry =
new System.DirectoryServices.DirectoryEntry(path);
System.DirectoryServices.DirectorySearcher mySearcher = new
System.DirectoryServices.DirectorySearcher(entry);
mySearcher.Filter = "(anr=" + userid + ")";
try {
foreach (System.DirectoryServices.SearchResult result in
mySearcher.FindAll()) {
DirectoryEntry oUser;
oUser = new DirectoryEntry(result.GetDirectoryEntry().Path);
object groups = oUser.Invoke("Groups");
foreach (object group in (IEnumerable)groups) {
DirectoryEntry groupEntry = new DirectoryEntry(group);
ret.Add(groupEntry.Name.Substring(groupEntry.Name.LastIndexOf("CN=") + 3));
} } }
catch (Exception) { }
return ret;
}
再修改Projects\Rainbow.Framework.Core\Security\Security.cs的 public static bool IsInRole(string role) ,令其正確判斷user是否為正確的群組。由於找不到AD群組,因此改成在SQL找到同名的Role時一樣有效,這樣也是另類的整合認證。

改到這裏已經可以利用AD控制授權,接下來就得想辦法把舊版的Rainbow Portal升級。

Update: VB超人提供VB6.0列舉AD群組的方法,請看

星期三, 一月 16, 2008

Rainbow Portal 2.0 NTLM 網域整合Hack

Rainbow Portal雖然有小進展,其實搬到以後還是有如龜速。

的2.0下載是假的2.0,其實是用.net 1.1的dll兜起來,做夢也沒想過有這種做法 Orz
要選RainbowPortal2.0.Beta1,也就是標示為Rainbow Portal 2.1.0.1882 Beta 1的版本。

在此要感謝不愧為MCAD.Net的同事Joseph,指出在WebSites\App_Code\Global.asax.cs下手。打開Global.asax.cs會發現原來的LDAP整合code全都remark起來,所以從這裏開始惡搞(Hack)。
一定要聲明,這是惡搞,並不是正確的作法。正確作法應該要實作MemberShipProvider,例如ADMemberShipProvider之類。

在Application_AuthenticateRequest方法裏找到適當的位置,加入:
if (context.User is WindowsPrincipal)
{
Rainbow.Framework.Users.Data.UsersDB accountSystem = new Rainbow.Framework.Users.Data.UsersDB();
string userid = Request.ServerVariables["Logon_User"]; //檢查User是否存在 Rainbow.Framework.Providers.RainbowMembershipProvider.RainbowUser rainbowUser = accountSystem.GetSingleUser(userid);
if (rainbowUser == null)
{
//不存在則加入並登入,底下這個Employee class是我自己寫的,請依照自己的情況寫
Rainbow.Framework.Helpers.Employee employee = new Rainbow.Framework.Helpers.Employee(userid);
// 檢查是否為合法的員工
if (employee.isValid())
{
string password="隨便";
//Rainbow會用email作為username,因此改用自己Hack的AddUser,後面會提到
Guid newUserId = accountSystem.AddUser(userid, employee.getUserName(), email, password); }
}
//幫User登入
PortalSecurity.SignOn(userid, strangePassword, true);
}


Projects\Rainbow.Framework.Core\Security\Security.cs的IsInRole(string role)會出問題,改成 public static bool IsInRole(string role) {
bool useNTLM = HttpContext.Current.User.Identity.AuthenticationType == "NTLM";
if (useNTLM) {
if (role.Trim() == "Admins") {
PortalSettings portalSettings = (PortalSettings)HttpContext.Current.Items[strPortalSettings];
StringBuilder winRoles = new StringBuilder();
winRoles.Append(portalSettings.CustomSettings["WindowsAdmins"]);
winRoles.Append(";");
winRoles.Append(Config.ADAdministratorGroup);
return IsInRoles(winRoles.ToString());
}
if (role == HttpContext.Current.User.Identity.Name) {
return true;
}
return false;
} else {
bool bl = false;
try {
bl = HttpContext.Current.User.IsInRole(role);
}
catch (Exception ) { }
return bl;
}
}

再來是adduser的部份,在Projects\Rainbow.Framework.Core\DAL\UsersDb.cs加上這個method
public Guid AddUser(string userid, string fullName, string email, string password)
{
Guid newUserId = AddUser(userid, string.Empty, string.Empty, string.Empty,
string.Empty, string.Empty, 0, string.Empty, string.Empty, password, email, false);

RainbowUser user = MembershipProvider.GetUser(newUserId, false) as RainbowUser;
user.Name = fullName;
MembershipProvider.UpdateUser(user);
return newUserId;
}

這樣就有個具有.Net 2.0版的NTLM整合Rainbow,可以作為企業內網用。

星期日, 八月 26, 2007

3rd Party database Provider for Windows

Postgresql .Net data provider (Npgsql)
PostgreSQL OLE DB Provider (PgOleDb)
PostgreSQL ODBC Driver (psqlODBC)
PostgreSQL JDBC Driver

MySQL ADO.Net provider
unofficial: MySQL OLE DB Provider another: MyOleDB
MySQL Connector/ODBC
MySQL JDBC Driver
MySQL Visual Studio Plugin

ADO.NET 2.0 Provider for SQLite (System.Data.SQLite)
SQLite OLE DB Provider
SQLite ODBC Driver
SQLite JDBC Driver

Oracle Data Provider for .NET
Oracle Providers for ASP.NET
Oracle OLE DB Provider
Oracle ODBC Drivers for Windows
Oracle SQLJ/JDBC

星期二, 八月 14, 2007

踏到asp.net的地雷

為什麼沒事會去試Rails呢?因為我踏到asp.net的地雷!在Windows 2000上用ASP.Net 2.0寫個簡單到不行的維護介面遇到 Invalid Viewstate錯誤,找到:
Intermittent Invalid Viewstate Error in ASP.NET Web pages
無效的 Viewstate 間歇性的錯誤在 ASP . NET Web 網頁

官方的解決方法:
1. 調整應用程式集區上設定。
2. 使用特定金鑰 machine.config 中, 以防止在每個處理序啟動時自動產生金鑰
3. 只張貼到相同的 ASPX 頁面
4. 關閉防火牆和防毒軟體
這樣的解決方式,我實在難以接受。因為:
1. 已經調整成獨立集區,沒用。
2. 這有點白痴,我不想做。
3. 原來就是post back到同一頁。
4. 關閉防毒軟體請恕我做不到,Windows實在太容易中毒。
5. 以上訊息是針對asp.net 1.1,不見得適用asp.net 2.0。

我仔細想想,會不會是Ajax.asp.net造成的?還是Windows 2000 Server造成的,但另一台Windows 2000 Server掛一堆服務都沒事。所以,我打算找個Open Source的solution,至少出問題時我能trace server呀!

星期日, 七月 01, 2007

彩虹入口搬家了

一直覺得Rainbow Portal比不上DotNetNuke有朝氣,開發一直停在去年3月Novell版本,這幾天才發現code搬到這裏了。

是Sourceforge太遜了嗎?先搬到Novell,又變成Google Code。嗯,懶得看文件了,先試再說。
有新版當然是好事,不過修改的幅度並不大,有點失望。而且從1.6版(Rainbow 2006)開始發生問題的NT網域整合認證還是不行,所以我只能繼續使用1.5版(Rainbow 2005)。

星期三, 一月 24, 2007

ASP.NET AJAX 1.0 推出

在2007/01/23,微軟正式推出ASP.NET 2.0 AJAX Extensions 1.0,至於ASP.NET AJAX Control Toolkit和ASP.NET AJAX Futures也有對應的版本,但ASP.NET AJAX Futures仍是CTP。
此版本建議在安裝前先裝Visual Studio 2005 Service Pack 1 。

我原本安裝的是1.0 CTP,升級後原來的web.config又不能用,建議產生一個新專案,把自訂的部份重新加上去,再copy回原專案。

說真的,我還是比較喜歡Beta版時copy一個dll放進去,至少改版後還能繼續用。希望以後更新版不需要再改web.config,否則每次升級都改也很累人呀~

如果用1.0 之前的版本寫結果tag不合,請看這裏的Migration Guides,手動修正tag。如果像我只是玩票性質,就重拉control吧 :P

星期四, 一月 04, 2007

asp.net架站要注意

同事傳給我一個url(https://books.tca.org.tw/book_contect.aspx?bno=EKS515(95)),結果笨笨的msn弄成(https://books.tca.org.tw/book_contect.aspx?bno=EKS515(95)),少了最後的括號。
結果出現:

'/' 應用程式中發生伺服器錯誤。

從型別 'DBNull' 轉換為型別 'Integer' 是無效的。

用asp.net佈署後,要記得改web.config,<compilation debug="true">改為<compilation debug="false">
會出現以上訊息,表示他把預設的<customErrors mode="RemoteOnly" /> 改成<customErrors mode="Off" /> ,否則只會在Web Server本機看到完整訊息。

星期三, 八月 23, 2006

asp.net切換執行身份

有時候為了在伺服器端列印或是連接網路磁碟等因素必須使用不同的身份,asp.net切換執行身份有兩種方式,一種是在web.config指定impersonate="true"
<system.web>
<identity impersonate="true" username="app1"
password="app1pw">
</identity>
</system.web>

這種作法會讓整個web ap下的執行身份都變成這個user,比較容易有安全性漏洞。
當然也可以把上面這段放在location區段下,變成

<location path="app1" allowoverride="false">
<system.web>
<identity impersonate="true" username="app1"
password="app1pw">
</identity>
</system.web>
</location>

另一種方式用Windows API去做impersonate,
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext;

[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);



public bool ImpersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}

public void UndoImpersonation()
{
if(impersonationContext != null)
impersonationContext.Undo();
}
這樣做在程式碼裏就可以直接切換執行身份,但問題又來了,在XP/2003是可以正常執行,在Win2000 Pro或Server都不行,必須在控制台->系統管理工具->本機安全性原則->本機原則->使用者權限指派->「作為作業系統的一部份」權限授與 ASP.NET 處理序帳戶。
微軟說這樣做將會造成安全上的危險,自己看著辦,不然就花錢升級吧!但到時候asp執行有問題或是權限不會設定可別找我,微軟都有密技可以處理。