如何使用 GridView 的分頁功能

0 comments
ASP.NET 2.0 的 GridView 控制項具有內建的分頁功能,只要透過 DataSourceID 屬性,指定支援直接分頁功能的資料來源控制項(如 SqlDataSource),並將 AllowPaging 屬性設定為 true,即可啟用分頁功能,而不需撰寫任何程式碼。

當使用 DataSourceID 屬性指定資料來源時,則資料控制項(Data-bound Control)就會在執行階段 (Run-Time)自動繫結資料來源控制項。相較於使用 DataSource 屬性,最大的不同就是你就必須明確呼叫 DataBind 方法來繫結資料來源。

所以,如果你是透過 GridView 控制項的 DataSource 屬性繫結資料來源,則當你移動 GridView 控制項的分頁時,便會引發如下的錯誤:
由 GridView 'GridView1' 引發但尚未處理的事件 PageIndexChanging。

這時你必須建立 GridView 控制項的 PageIndexChanging 事件處理常式,為 GridView 控制項指定使用者所選取之頁面的索引,並呼叫 DataBind 方法:
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
GridView1.DataBind();
}

繼續閱讀...

如何使用 OpenDataSource 查詢文字檔

0 comments
OpenDataSource 提供了特定(Ad Hoc)連線資訊作為包含四個部份的物件名稱(Four-part Name)的一部份,而不需使用連結伺服器的名稱。四個部分的名稱一般用於分散式查詢,其格式如下:
linkedserver.catalog.schema.object_name

以下範例藉由 OLE DB Provider for Jet 來查詢文字檔 (test.txt):
select * from OpenDataSource('Microsoft.Jet.OLEDB.4.0', 'Data Source = C:\; Extended Properties = "Text;HDR=NO"')...test#txt

事實上 OpenDataSource 函數就位於前面提到的四個部份的物件名稱中的 linkedserver 位置,所以你應把它視為伺服器,而 test.txt 就是資料表。記得,因為逗點是物件識別名稱的一部份,所以你必須將檔名中的逗號使用 # 符號取代。

連線字串中的 Data Source 需指定來源檔案的所在目錄。Extended Properties 必須包含 Text;除此之外,你可以選擇性指定 HDR=NO 表示文字檔的第一列沒有包含欄位標題,這時 SQL Server 將會自動以 F1 、 F2 、 F3 ... 來命名資料欄位。以上面的查詢範例來說,只能針對以號分隔的文字檔輸出資料欄位,如果你需要查詢特定格式的資料,則必須在 Data Source 目錄下建立 Schema.ini 來指定查詢參數。有關如何建立 Schema.ini 檔的詳細資訊可以參考這裡

以下的 Schema.ini 範例,描述 test.txt 是使用 tab 分隔的文字檔:
[test.txt]
Format=TabDelimited
ColNameHeader=False
MaxScanRows=0
CharacterSet=ANSI

參考文章:
OPENDATASOURCE (Transact-SQL) by Microsoft
Schema.ini File (Text File Driver) by Microsoft

繼續閱讀...

Crystal Reports - 如何在交叉表加入總和百分比

6 comments
本文以 Crystal Reports XI 說明如何使用百分比摘要函數為交叉表加入總和百分比。以下將會逐步說明,帶你完成簡單的銷售報表。

新增報表
請在 Crystal Reports 新增空白報表,並在資料來源設定中,使用 SQL Server 範例資料庫 pubs 作為報表資料來源,並加入以下查詢命令:
SELECT 
stor_name, 'Qtr' + CAST(DATEPART(quarter,ord_date) AS CHAR) AS [quarter],
sum(qty) AS qty
FROM
sales INNER JOIN
stores ON sales.stor_id = stores.stor_id
WHERE YEAR(ord_date) = 1993
GROUP BY stor_name, 'Qtr' + CAST(DATEPART(quarter,ord_date) AS CHAR)

加入群組
在功能表中選擇 [插入]->[群組],分別插入 [命令.stor_name]、[命令.quarter] 兩個資料欄位作為群組依據。

建立公式欄位
建立一個名為 percent_of_total 的公式欄位,並輸入以下公式:
PercentOfSum({命令.qty},{命令.quarter})

加入交叉表
  1. 在功能表中選擇 [插入]->[交叉表...],將交叉表置於 [報表首],並按滑鼠右鍵點選功能表中的 [交叉表專家...]。
  2. 在 [交叉表專家] 視窗中,將交叉表 [可使用的欄位] 中的 [命令.stor_name]、[命令.quarter] 兩個資料欄位,分別加入交叉表的資料列及資料欄,並在摘要欄位加入 [命令.qty] 資料欄位及 [percent_of_total] 公式欄位。
  3. 在摘要欄位中點選 [@percent_of_total 的總和],接著按下位於下方的 [變更摘要...] 按鈕。
  4. 在[編輯摘要]視窗中,在[計算這個摘要]的下拉選單中選擇 [總和],在 [選項] 區段中,啟用從 [資料行] 來 [顯示成百分比]。
  5. 點選 [自訂樣式] 頁籤,在 [摘要欄位] 選項中,點選 [水平],並取消位於 [格線選項] 中 [資料行總和在上方] 及 [資料列總和在左邊] 核取方塊。
  6. 按下 [確定] 按鈕,關閉 [交叉表專家] 視窗。


最後,再隱藏不必要顯示的區段,報表就大致完成了。

繼續閱讀...

解決 ADO.NET 建立 Oracle 資料庫連線的問題

0 comments
當你在 ASP.NET 嘗試使用 System.Data.OleDb.OleDbConnection 來開啟 Oracle 資料庫連線時,可能會發生如下的錯誤訊息:
找不到 Oracle 用戶端及網路元件。這些元件由 Oracle 公司供應且為 Oracle 8i 以上版本用戶端軟體安裝的一部分。在安裝這些元件前您無法使用此提供者。

如果是使用 System.Data.OracleClient 則會發生如下的錯誤訊息:
System.Data.OracleClient requires Oracle client software version 8.1.7 or greater.

因為使用 .NET Framework Data Provider 存取 Oracle 資料庫,需要安裝 Oracle 用戶端軟體 8.1.7 版及更新版本。如果你是在未安裝 Oracle 用戶端軟體的情況下發生這樣的問題,你可以造訪 Oracle 官方網站,下載 Oracle Data Access Components (ODAC)。下載完成後,請執行安裝程式,並在安裝過程中選擇安裝 Oracle Data Provider for .NET。

若是在已安裝 Oracle 用戶端軟體的情況下,可能是 ORACLE_HOME 安裝在 Windows NTFS 磁碟分割區, 導致 ASP.NET 所使用的 Authenticated User 權限找不到 ORACLE_HOME 目錄,才導致這樣的錯誤。在 roytore 所發表的文章中,有提到針對此問題的解決作法:
  1. 以管理者身分登入 Windows。
  2. 使用檔案總管開啟 ORACLE_HOME 資料夾的內容對話盒,並點選 [安全性] 頁籤。
  3. 在群組或使用者清單中,點選 [Authenticated Users]。在下方權限清單中,取消 [讀取及執行] 項目的核取方塊,並按下 [套用]。
  4. 接著按下 [進階] 按鈕,確認 [Authenticated Users] 的權限是 [讀取及執行],且套用在 [這個資料夾,子資料夾及檔案]。
  5. 按下 [確定] 按鈕,直到關閉資料夾內容對話盒。
  6. 重新啟動 Windows。

相關下載:
Oracle Data Access Components (ODAC) Downloads

參考文章:
System.Data.OracleClient requires Oracle client software version 8.1.7 or greater.
by roytore

繼續閱讀...

ASP.NET Single Sign-On

0 comments
如果在相同網域下,建置多個跨伺服器的 ASP.NET 應用程式時,你可以啟用跨應用程式的表單驗證(Forms Authentication),提供單一登入(Single Sign-On)驗證,使用者就不需在切換應用程式時重新驗證。


如果使用表單驗證,則參與共用表單驗證的所有應用程式都要使用相同的機器金鑰(Machine Key)。機器金鑰會是用於檢視狀態(ViewState)及表單驗證票證(Forms Authentication Tickets)的加密、解密以及驗證,在 .NET Framework 1.1 版是定義在 Machine.config 中的 <machineKey> 項目,其預設組態如下:
<machineKey validationKey="AutoGenerate,IsolateApps" decryptionKey="AutoGenerate,IsolateApps" validation="SHA1"/>

在 .NET Framework 2.0 則是定義在 Machine.config.comments,其預設組態如下:
<machineKey validationKey="AutoGenerate,IsolateApps" decryptionKey="AutoGenerate,IsolateApps" validation="SHA1" decryption="Auto" />

validationKey 屬性值用於建立驗證表單票證的 HMAC 碼(Hashed Message Authentication Code)。decryptionKey 屬性值是用於加密和解密表單驗證票證的金鑰。validation 屬性則是表示產生 HMAC 碼時是使用何種演算法。decryption 屬性是 .NET Framework 2.0 新增的屬性,AES 是解密資料的預設演算法。

所以,如果你沒有在 <machineKey> 項目指定金鑰,預設的組態設定就會使 ASP.NET 為不同的應用程式產生唯一的加密金鑰。因此,若要達到跨應用程式的表單驗證的目的,你就必須覆寫 <machineKey> 項目,為所有 Web 伺服器設定相同的驗證金鑰及相同的驗證演算法。如果組態不一致,Cookie 就不能共用。你可以使用 RNGCryptoServiceProvider 類別自行產生給你所有應用程式通用的驗證金鑰 (validationKey)和解密金鑰(decryptionKey)。

如果你需要 ASP.NET 2.0 的應用程式可以與 ASP.NET 1.1 共用表單驗證票證資訊,則必須在每個 ASP.NET 2.0 應用程式的 <machineKey> 項目組態中加入 decryption="3DES",這是因為在 ASP.NET 1.1 中,是使用 3DES 演算法來加密和解密表單驗證票證。以下是組態設定範例:
<system.web>
<machineKey validationKey="F40C0FF602CF4181C15AA3E494EBC04B8D2C6654A54DD6C12CE39643D0D864CD685C701A655B622C04DCED8B36A1E2B7B5BDDB9F769BEB040FE31974E6FBFBC1" decryptionKey="8CF1335D3E93BBA2F6C3F6A6BF88F37685F4E3979B3A8511" validation="SHA1" decryption="3DES" />
<system.web>

登入驗證
在登入網頁建立自訂的驗證程式碼,檢查使用者名稱與密碼,如果驗證成功,就為該使用者建構 Principal 物件,並將它存入 HttpContext.User 中。在傳送表單驗證 Cookie 到用戶端前,你必須先設定 Cookie 的 Domain 屬性。以下是實作登入網頁的範例程式碼:
protected void _btnLogin_Click(object sender, EventArgs e)
{
SitePrincipal principal = SitePrincipal.ValidateLogin(_txtUserName.Text, _txtUserPass.Text);
if(principal != null)
{
Context.User = principal;
HttpCookie cookie =
FormsAuthentication.GetAuthCookie(principal.Identity.Name, _chkAutoLogin.Checked);
cookie.Domain = "yourwebsite.com";
Response.AppendCookie(cookie);
Response.Redirect(
FormsAuthentication.GetRedirectUrl(principal.Identity.Name, _chkAutoLogin.Checked));
}
else
{
_lblMessage.Text = "Wrong username or password";
}
}

程式碼所使用的 SitePrincipal 類別是實作 System.Security.Principal.IPrincipal 介面的自訂類別,請自行下載原始碼引用到你的應用程式。

啟用表單驗證
<system.web>
<authentication mode="Forms">
<forms name=".YourAppName" loginUrl="Login.aspx" protection="All" timeout="30" path="/" />
</authentication>
</system.web>

你應該在 <forms> 項目指定自己的 name 及 path 屬性,並且必須確定在你的所有的應用程式中保持一致的組態設定。protection 屬性是用來指定保護 Cookie 的方法,其預設值為 All(也是建議值),這會使 ASP.NET 同時使用驗證和加密金鑰來保護 Cookie。

處理驗證要求
在應用程式初始驗證要求時,你還必須檢查使用者是否已經過驗證。如果順利取得 Cookie,接著就可進行票證解密,取得使用者資訊,建立 Principal 物件。請在所有應用程式的 Global.asax 實作 Application_AuthenticateRequest 事件處理常式:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if(authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
string userName = authTicket.Name;
SitePrincipal principal = new SitePrincipal(userName);
Context.User = principal;
}
}

當呼叫 FormsAuthentication.Decrypt 方法擷取表單驗證 Cookie 時,會參考 <machineKey> 項目中的指定的 decryptionKey 值解密票證值。

登出機制
從應用程式中登出該使用者,通常只要使用 System.Web.Security.FormsAuthentication.SignOut() 就可以從瀏覽器移除表單驗證 Cookie。但是 SignOut() 方法無法處理有網域關聯的 Cookie,所以你必須手動移除表單驗證 Cookie。以下是實作登出網頁的範例程式碼:
private void Page_Load(object sender, System.EventArgs e)
{
System.Web.HttpCookie cookie =
Request.Cookies[System.Web.Security.FormsAuthentication.FormsCookieName];

if (cookie!=null)
{
cookie.Domain = "yourwebsite.com";
cookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(cookie);
}

if (Request.QueryString["ReturnURL"]!=null)
{
Response.Redirect(Request.QueryString["ReturnURL"]));
}
else
{
Response.Redirect("~/Default.aspx");
}
}

完成後,你就可以在頁面程式碼中,使用 Request.IsAuthenticated 屬性檢查目前的連線要求是否驗證成功。以下是在 Page_Load 事件處理常式的範例程式碼:
private void Page_Load(object sender, System.EventArgs e)
{
if (!Request.IsAuthenticated)
{
Response.Redirect(string.Format("~/Login.aspx?ReturnURL={0}",
Server.UrlEncode(Request.PathInfo)));
}
}

相關資源:
Understanding the Forms Authentication Ticket and Cookie by Microsoft

參考資料:
Single sign-on across multiple applications in ASP.NET by Michal Altair Valasek
建置安全的 ASP.NET 應用程式: 驗證、授權和安全通訊 by Microsoft
How To: Configure MachineKey in ASP.NET 2.0 by Microsoft
How To: Protect Forms Authentication in ASP.NET 2.0 by Microsoft
Explained: Forms Authentication in ASP.NET 2.0 by Microsoft
驗證與授權 (探索 .NET) by Microsoft

繼續閱讀...

ASP.NET 上傳檔案的限制

4 comments
當你在 ASP.NET 2.0 使用 FileUpload 控制項上傳超過 4MB 的檔案時,可能會面臨無法上傳的問題。這是因為上傳內容的長度超過了 maxRequestLength 參數在 Machine.config 檔案所定義的預設上限值 4096 (4 MB),這個限制是 ASP.NET 為了要預防可能的「拒絕服務」攻擊(Denial of Service attacks)。你可以在 Web.config 檔案中,覆寫應用程式 maxRequestLength 的值。例如,下列的 Web.config 設定會允許最大 10 MB 的檔案上傳:
<System.Web>
<httpRuntime maxRequestLength="10240" />
</System.Web>

但是,只要 POST 請求的內容(例如上傳檔案)超過 Web.config 的 maxRequestLength 設定,用戶端就會收到以下的錯誤訊息:「無法顯示網頁:找不到伺服器或 DNS 錯誤」。如果你試圖要在 Page 層級處理這個錯誤將會徒勞無功,因為這是屬於 Application 層級的錯誤,也就是 ASP.NET 早在執行你的網頁程式碼之前,就已經拋出「超出最大的要求長度」的例外。比較好的處理方式是在 Global.asax 加入 Application_BeginRequest 事件處理常式,在檔案未上傳前,先檢查 HTTP 標頭內容的長度,如果超過 maxRequestLength 的設定値,便將用戶端重新導向導引到自訂的錯誤頁面。以下是在 Global.asax 檔案中建立錯誤處理程序的程式碼:
<%@ Application Language="C#" %>
<%@ Import Namespace="System.Web.Configuration" %>
<script runat="server">

void Application_BeginRequest(object sender, EventArgs e)
{
HttpRuntimeSection section = (HttpRuntimeSection)ConfigurationManager.GetSection("system.web/httpRuntime");
int maxFileSize = section.MaxRequestLength*1024;

if (Request.ContentLength > maxFileSize)
{
Response.Redirect("~/FileTooLarge.aspx");
}
}
</script>

繼續閱讀...

資料庫物件命名原則

2 comments
程式設計使用命名慣例及有意義的名稱,會讓程式容易閱讀,而資料庫設計也應該如此。如果你希望自己的系統具可維護性(Maintainability),你就不應該草率的命名你的資料庫物件。採用命名原則的目的,是為了能夠讓資料庫物件名稱擁有足夠資訊,讓自己或是其他開發成員能清楚知道物件的類型及其使用目的。

本文將針對以下資料庫物件來說明:
  1. 資料表(Tables)
  2. 資料欄位(Columns)
  3. 檢視表(Views)
  4. 預儲程序(Stored Procedures)
  5. 觸發程序(Triggers)

所有的資料庫物件命名都應該遵循以下規則:
  1. 若未超過長度,限制應避免使用縮寫。
  2. 使用 Pascal 大小寫命名法,前綴詞則使用 Camel 命名法。
  3. 使用英文字母或底線字元組合,數字應盡量避免。
  4. 不要以底線字元當字首

若因長度的限制而需要使用縮寫時,應遵從以下的規則:
  1. 縮寫的第一個字元應該與單詞的第一個字母相同。
  2. 兩個字母的縮略字使用全大寫字母,而三個以上之字元的縮略字則使用 Pascal 大小寫慣例。遵守命名慣例的範例:ID、DB、Sql。違反命名慣例的範例:Id、Db、SQL。
  3. 不要使用任何不被廣泛接受的縮略字。

資料表(Tables)
資料表應該使用複數名稱,例如:Employees。若名稱由多個單詞組成,則只有最後一個單詞使用複數,例如:UserRoles。

如果資料表是屬於多對多關聯性(Many-To-Many Relationship)的聯合資料表(Junction Table),也就是該資料表的主索引鍵是由由資料表 A 和資料表 B 兩者的外部索引鍵所組成,就要連結資料表 A 和資料表 B 的名稱來命名。例如,Authors 資料表和 Titles 資料表之間具有多對多關聯性,而你需要一個資料表來維持這兩個資料表彼此之間的多關聯性,則這個資料表就應該命名為 TitlesAuthors。

資料欄位(Columns)
因為資料欄位是資料表的成員,所以欄位名稱不應再列入冗餘的資料表名稱。

檢視表(Views)
檢視表應比照資料表命名規則,但為有別於資料表,應加入前綴詞以避免混淆,例如:vw_Users。

預儲程序(Stored Procedures)
{Table Name}_{Action}[Qualifier]

  • Table Name:預儲程序主要作用的資料表名稱。如果沒有作用在資料表上,就使用 Util(Utility的簡寫)來命名。
  • Action:這部份指的是作用到資料表的主要動作,例如:Create、Get、Update、Delete。如果是 Util 程序,這個部份就不一定要加上。
  • Qualifier:可以選擇性用來更清楚描述這個預儲程序要進行的動作。

觸發程序(Triggers)
{Prefix}_{Table Name}_{Actions Covered}
  • Prefix:使用 trg_ 做為前綴詞,以別於其他資料庫物件。
  • Table Name:執行觸發程序所在的資料表名稱。
  • Actions Covered: 啟動觸發程序的 Insert、Update、Delete 選項。在此用 "Ins"、"Upd"、"Del" 來描述。


參考文章:
Database Object Naming Rules by sbates
DevCampus Database Naming Conventions by Jason Mauss
Database object naming conventions by Vyas

繼續閱讀...

定序衝突 (Transact-SQL)

1 comments
當你的 SQL 查詢試圖去比較不同定序的資料欄位時,就會出現如下類似的錯誤訊息:
訊息 468,層級 16,狀態 9,行 1
無法解析 equal to 作業中 "Latin1_General_CI_AI" 與 "Chinese_Taiwan_Stroke_CI_AS" 之間的定序衝突。

以下是在 SQL Server 2005 所引發錯誤的 SQL 查詢範例:
select * from sysobjects o
left join ::fn_Listextendedproperty(null, N'user',N'dbo',N'table', default, null, null) e on o.name = e.objname
where type = 'U'

當你在定序為 Chinese_Taiwan_Stroke_CI_AS 的資料庫,使用 fn_Listextendedproperty 函式與 sysobjects 資料表合併查詢時,就會發生定序衝突(Collation Conflict)的錯誤。這是因為 fn_Listextendedproperty 函式回傳的資料固定是以 Latin1_General_CI_AI 為定序,所以導致定序不一致的情況。

上例的解決作法就是在運算式中,做明確的字串定序轉換,如以下範例:
select * from sysobjects o
left join ::fn_Listextendedproperty(null, N'user',N'dbo',N'table', default, null, null) e on o.name = e.objname COLLATE Chinese_Taiwan_Stroke_CI_AS
where type = 'U'

你也可以利用 COLLATE 子句中的 database_default 選項,指定特定的資料行使用目前連接的使用者資料庫之定序預設值。

繼續閱讀...

為你的網站部署 P3P 隱私權政策

1 comments
P3P 是由全球資訊網協會(W3C,World Wide Web Consortium)所發展出的隱私權偏好平台(Platform for Privacy Preferences),它一種標準通訊協定及結構,Web 伺服器可以使用 P3P,清楚的描述網站的資料收集及隱私權原則。當你瀏覽網站時,具備 P3P 功能的瀏覽器會判斷你的隱私權偏好選項是否與網站的隱私權原則和使用者的隱私權配置相符。而 Internet Explorer 6 就是第一個支援 P3P 標準的瀏覽器,他提供六種預設的使用者隱私權設定,從接受所有 cookie 到封鎖所有 cookie 都有。在預設的情況下,當 Web 伺服器的隱私權原則和使用者的隱私權配置不一樣時,IE 會選擇性地封鎖不同類型的 cookie,並針對不符合你的隱私權設定的網站向你發出警示。


要部署 P3P 前,必須先建立三個檔案:
  1. 描述隱私權保護政策的 HTML 網頁,其檔名為 policy.html。
  2. 完整的 P3P 隱私權原則檔,其檔名為 policy.xml。
  3. 原則參考檔,其檔名為 p3p.xml。
首先要把給 HTML 格式的隱私權保護政策網頁的內容依據 P3P specification 來建立 XML 格式的 P3P 隱私權原則檔案;但 P3P 規格非常複雜,強烈建議使用 P3P 編輯工具,如:
  1. IBM P3P Policy Editor
  2. PrivacyBot.com
  3. P3PEdit
這些編輯器會協助你產生 policy.xml、p3p.xml,以下是 policy.xml 的範例:
<POLICY xmlns="http://www.w3.org/2000/12/p3pv1"
discuri="http://網域名稱/policy.html"
opturi="http://網域名稱/policy.html">
<ENTITY>
<DATA-GROUP>
<DATA ref="#business.name">公司名稱</DATA>
<DATA ref="#business.contact-info.postal.street">地址</DATA>
<DATA ref="#business.contact-info.postal.city">城市</DATA>
<DATA ref="#business.contact-info.postal.postalcode">郵遞區號</DATA>
<DATA ref="#business.contact-info.postal.country">國家</DATA>
<DATA ref="#business.contact-info.online.email">電子郵件</DATA>
<DATA ref="#business.contact-info.telecom.telephone.number">電話號碼</DATA>
</DATA-GROUP>
</ENTITY>
<ACCESS><nonident/></ACCESS>
<STATEMENT>
<PURPOSE><admin/><develop/></PURPOSE>
<RECIPIENT><ours/></RECIPIENT>
<RETENTION><stated-purpose/></RETENTION>
<DATA-GROUP>
<DATA ref="#dynamic.clickstream.server"/>
<DATA ref="#dynamic.http.useragent"/>
</DATA-GROUP>
</STATEMENT>
<STATEMENT>
<PURPOSE><pseudo-analysis required="opt-in"/></PURPOSE>
<RECIPIENT><other-recipient/></RECIPIENT>
<RETENTION><indefinitely/></RETENTION>
<DATA-GROUP>
<DATA ref="#user.home-info.postal.postalcode">
<CATEGORIES><demographic/></CATEGORIES>
</DATA>
</DATA-GROUP>
</STATEMENT>
</POLICY>

根據上面的文件內容,再轉成「P3P 精簡原則」(P3P compact policy)代碼:
NOI ADM DEV PSAi COM NAV OUR STP IND DEM

例如:在 ACCESS 元素包含的文字 <nonident/> 及 CATEGORIES 元素包含的文字 <demographic/> 分別表示為 NOI、DEM 。如果你是使用編輯器,這部份當然就不用操心了,因為編輯器會自動產生給你。這些精簡原則代碼所代表的意義如下:
  1. NOI 未收集個人可識別資訊。
  2. ADM 資料是為了網站管理而被使用。
  3. DEV 資料是為了研究而被使用。
  4. PSAi 非已識別的相關資訊將被用來做研究、分析及報告。例如某個郵遞區號的使用者人數。
  5. COM 電腦資訊將被收集。
  6. NAV 導覽與點擊串流資料將被收集。
  7. OUR 資料只給我們自己與我們的代理者使用。
  8. STP 資料是按收集目的被保留。
  9. IND 資料被保留的期限沒有明確指定。
  10. DEM 個人特徵資料將會被收集,例如性別、年齡及收入。
最後是 p3p.xml 檔,它必須參照到完整的隱私權原則:
<META xmlns="http://www.w3.org/2000/12/p3pv1">
<POLICY-REFERENCES>
<POLICY-REF about="policy.xml">
<INCLUDE>\*</INCLUDE>
<COOKIE-INCLUDE name="*" value="*" domain="*" path="*"/>
</POLICY-REF>
</POLICY-REFERENCES>
</META>

其中, POLICY-REF 元素的 about 屬性就是指向 policy.xml ,這也正是 p3p.xml 的目的。

接下來就是部署 P3P 到你的 Web 伺服器:
  1. 將原則參考(policy-reference)檔案 p3p.xml 部署到 /w3c/p3p.xml。
  2. 將完整的隱私權原則檔案部署到相同目錄,例如:/w3c/policy.xml。
  3. 將原則摘要加入 HTTP 標頭。

使用 HTTP 標頭
以網路資訊服務(IIS)管理員為例:
  1. 開啟網路資訊服務(IIS)管理員。
  2. 開啟網站內容視窗。
  3. 點選[HTTP 標頭]頁簽。
  4. 在[自訂 HTTP 標頭]處,按下[新增]按鈕。
  5. 在[自訂標頭名稱]欄位輸入 P3P
  6. 在[自訂標頭值]欄位輸入隱私權摘要字串,例如:CP="NOI ADM DEV PSAi COM NAV OUR STP IND DEM"
  7. 按下[確定],並離開資訊服務(IIS)管理員。
除了在 IIS 使用 HTTP 標頭外,你也可以寫程式輸出自訂標頭來達到相同的目的。例如:在 ASP.NET 可以透過 global.asax 撰寫下列程式碼:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("p3p",
"CP=\"NOI ADM DEV PSAi COM NAV OUR STP IND DEM\"");
}

部署成功後,就可以打開瀏覽器檢視你的網站的隱私權政策,如果是使用 IE6 的話,請在[檢視]功能表,按一下[隱私權報告],就可以看到隱私權摘要報告。


參考資料:
How to Deploy P3P Privacy Policies on Your Web Site by Microsoft
The Platform for Privacy Preferences 1.0 Deployment Guide by W3C

繼續閱讀...

Crystal Reports - 設計 Master / Detail 報表

9 comments
本文使用 Crystal Reports XI 以簡單的出貨報表為範例,建立顯示訂單主檔的主報表及訂單明細檔的子報表,然後使用訂單編號當作參數,來連結這兩個報表。

建立子報表(訂單明細)
1.加入 SQL 查詢命令至報表:
SELECT OrderDetails.OrderNumber,OrderDetails.ProductID,
Products.Name,OrderDetails.UnitPrice,OrderDetails.Quantity,OrderDetails.ExtendedPrice FROM OrderDetails
INNER JOIN Products ON OrderDetails.ProductID=Products.ID
WHERE OrderDetails.OrderNumber={?訂單編號}
在命令中我加入了查詢參數{?訂單編號},所以必須在命令視窗右邊的參數清單建立名為訂單編號的命令參數,查詢參數才會有效。


2.在報表明細區段插入資料庫欄位後,將報表儲存為[訂單明細檔.rpt]。

建立主報表(訂單主檔)
1.加入 SQL 查詢命令至報表:
SELECT Orders.OrderNumber,Orders.ShipName,Orders.ShipCity,Orders.ShipPostalCode,
Orders.ShipAddress,Orders.OrderDate,Orders.ShippedDate
FROM Orders
WHERE Orders.OrderNumber={?訂單編號}
在命令中同樣也加入查詢參數{?訂單編號},所以也要在參數清單建立名為訂單編號的命令參數。

2.將訂單主檔的資料欄位插入頁首區段。

3.接著在訂單主檔下方插入子報表:[訂單明細檔.rpt]。

4.在主報表中點選[訂單明細檔.rpt],在滑鼠右鍵功能選單中選擇[變更子報表連結]。

5.在[子報表連結]視窗中,在主報表的[可使用的欄位]清單中,將[?訂單編號]加入[要連結的欄位]。然後,在[要使用的子報表參數欄位],選擇我們在子報表建立的[?訂單編號]參數,如此一來便會達到主報表與子報表共用參數的目的。完成後,按下確定關閉視窗。


6.最後將報表儲存,報表就完成了。

繼續閱讀...