標籤:one 通過 sed author enable 多個 iter des bar
web組件是ASP.NET WebForm裡面的伺服器控制項,它涵蓋的內容比較多,鑒於這種狀況的話鄙人不打算深究下去了,只是局限於瞭解web.config配置裡面的配置內容則可。
那麼也得稍微說說啥是Web組件。引用MSDN的話:ASP.NET Web 組件是一組整合控制項,用於建立網站使終端使用者可以直接從瀏覽器修改網頁的內容、外觀和行為。這些修改可以應用於網站上的所有使用者或個別使用者。還有引用它上面的插圖
看了這個之後我就感覺就類似於QQ個人空間上的各個面板或者OA系統上的面板,可以按照每個使用者的個人喜好去更改顯示的內容,位置以及是否顯示
更多關於Web組件的內容可參考本篇後面的參考的MSDN文章。關於Web組件的的WebPartManager和webParetZone就不說了,接下來則看看webParts配置節的內容
配置分兩大塊,personalization的是關於個人化資料的提供以及使用者存取權限的;另一個是關於web組件串連的時候資料結構不一致需要轉換的配置。
下面則先看看personalization的,這個例子是參考了MSDN。實現的效果大概是記錄使用者個人化資料,以及對資料的許可權控制,本例子包含一個登入頁面,一個樣本頁面,兩個使用者控制項。
首先樣本頁面的內容如下
登入頁面只是包含了一個登入控制項
用於展現使用者個人化的自訂控制項 Color
<%@ Control Language="C#" %><script runat="server"> // User a field to reference the current WebPartManager. private WebPartManager _manager; // Defines personalized property for User scope. In this case, the property is // the background color of the text box. [Personalizable(PersonalizationScope.User)] public System.Drawing.Color UserColorChoice { get { return _coloruserTextBox.BackColor; } set { _coloruserTextBox.BackColor = value; } } // Defines personalized property for Shared scope. In this case, the property is // the background color of the text box. [Personalizable(PersonalizationScope.Shared) ] public System.Drawing.Color SharedColorChoice { get { return _colorsharedTextBox.BackColor; } set { _colorsharedTextBox.BackColor = value; } } void Page_Init(object sender, EventArgs e) { _manager = WebPartManager.GetCurrentWebPartManager(Page); } protected void Page_Load(object src, EventArgs e) { // If Web Parts manager scope is User, hide the button that changes shared control. if (_manager.Personalization.Scope == PersonalizationScope.User) { _sharedchangeButton.Visible = false; if (!_manager.Personalization.IsModifiable) _userchangeButton.Enabled = false; } else { _sharedchangeButton.Visible = true; if (!_manager.Personalization.IsModifiable) { _sharedchangeButton.Enabled = false; _userchangeButton.Enabled = false; } } } // Changes color of the User text box background when button clicked by authorized user. protected void _userButton_Click(object src, EventArgs e) { switch(_coloruserTextBox.BackColor.Name) { case "Red": _coloruserTextBox.BackColor = System.Drawing.Color.Yellow; break; case "Yellow": _coloruserTextBox.BackColor = System.Drawing.Color.Green; break; case "Green": _coloruserTextBox.BackColor = System.Drawing.Color.Red; break; } } // Changes color of the Shared text box background when button clicked by authorized user. protected void _sharedButton_Click(object src, EventArgs e) { switch (_colorsharedTextBox.BackColor.Name) { case "Red": _colorsharedTextBox.BackColor = System.Drawing.Color.Yellow; break; case "Yellow": _colorsharedTextBox.BackColor = System.Drawing.Color.Green; break; case "Green": _colorsharedTextBox.BackColor = System.Drawing.Color.Red; break; } } </script><html xmlns="http://www.w3.org/1999/xhtml"><head> <title>WebParts Personalization Example</title></head><body><p> <asp:LoginName ID="LoginName1" runat="server" BorderWidth="500" BorderStyle="none" /> <asp:LoginStatus ID="LoginStatus1" LogoutAction="RedirectToLoginPage" runat="server" /></p> <asp:Label ID="ScopeLabel" Text="Scoped Properties:" runat="server" Width="289px"></asp:Label> <br /> <table style="width: 226px"> <tr> <td> <asp:TextBox ID="_coloruserTextBox" Font-Bold="True" Height="110px" runat="server" Text="User Property" BackColor="red" Width="110px" /> </td> <td> <asp:TextBox ID="_colorsharedTextBox" runat="server" Height="110px" Width="110px" Text="Shared Property" BackColor="red" Font-Bold="true" /> </td> </tr> <tr> <td> <asp:Button Text="Change User Color" ID="_userchangeButton" runat="server" OnClick="_userButton_Click" /> </td> <td > <asp:Button Text="Change Shared Color" ID="_sharedchangeButton" runat="server" OnClick="_sharedButton_Click" /> </td> </tr> </table></body></html>
用於顯示使用者個人化資料許可權的自訂控制項Persmode
1 <%@ control language="C#" %> 2 3 <script runat="server"> 4 5 // Use a field to reference the current WebPartManager. 6 private WebPartManager _manager; 7 8 protected void Page_Load(object src, EventArgs e) 9 { 10 // Get the current Web Parts manager. 11 _manager = WebPartManager.GetCurrentWebPartManager(Page); 12 13 // All radio buttons are disabled; the button settings show what the current state is. 14 EnterSharedRadioButton.Enabled = false; 15 ModifyStateRadioButton.Enabled = false; 16 17 // If Web Parts manager is in User scope, set scope button. 18 if (_manager.Personalization.Scope == PersonalizationScope.User) 19 UserScopeRadioButton.Checked = true; 20 else 21 SharedScopeRadioButton.Checked = true; 22 23 // Based on current user rights to enter Shared scope, set buttons. 24 if (_manager.Personalization.CanEnterSharedScope) 25 { 26 EnterSharedRadioButton.Checked = true; 27 No_Shared_Scope_Label.Visible = false; 28 Toggle_Scope_Button.Enabled = true; 29 } 30 else 31 { 32 EnterSharedRadioButton.Checked = false; 33 No_Shared_Scope_Label.Visible = true; 34 Toggle_Scope_Button.Enabled = false; 35 } 36 37 // Based on current user rights to modify personalization state, set buttons. 38 if (_manager.Personalization.IsModifiable) 39 { 40 ModifyStateRadioButton.Checked = true; 41 Reset_User_Button.Enabled = true; 42 } 43 else 44 { 45 ModifyStateRadioButton.Checked = false; 46 Reset_User_Button.Enabled = false; 47 } 48 } 49 // Resets all of a user and shared personalization data for the page. 50 protected void Reset_CurrentState_Button_Click(object src, EventArgs e) 51 { 52 // User must be authorized to modify state before a reset can occur. 53 //When in user scope, all users by default can change their own data. 54 if (_manager.Personalization.IsModifiable) 55 { 56 _manager.Personalization.ResetPersonalizationState(); 57 } 58 } 59 60 // Allows authorized user to change personalization scope. 61 protected void Toggle_Scope_Button_Click(object sender, EventArgs e) 62 { 63 if (_manager.Personalization.CanEnterSharedScope) 64 { 65 _manager.Personalization.ToggleScope(); 66 } 67 68 } 69 </script> 70 <div> 71 <asp:Panel ID="Panel1" runat="server" 72 Borderwidth="1" 73 Width="208px" 74 BackColor="lightgray" 75 Font-Names="Verdana, Arial, Sans Serif" Height="214px" > 76 <asp:Label ID="Label1" runat="server" 77 Text="Page Scope" 78 Font-Bold="True" 79 Font-Size="8pt" 80 Width="120px" /> <br /> 81 82 83 <asp:RadioButton ID="UserScopeRadioButton" runat="server" 84 Text="User" 85 AutoPostBack="true" 86 GroupName="Scope" 87 Enabled="false" /> 88 <asp:RadioButton ID="SharedScopeRadioButton" runat="server" 89 Text="Shared" 90 AutoPostBack="true" 91 GroupName="Scope" 92 Enabled="false" /> 93 <br /> 94 <asp:Label BorderStyle="None" Font-Bold="True" Font-Names="Courier New" ID="No_Shared_Scope_Label" Font-Size="Smaller" ForeColor="red" 95 runat="server" Visible="false" Width="179px">User cannot enter Shared scope</asp:Label> 96 <br /> 97 <asp:Label ID="Label2" runat="server" 98 Text="Current User Can:" 99 Font-Bold="True"100 Font-Size="8pt"101 Width="165px" />102 <br />103 <asp:RadioButton ID="ModifyStateRadioButton" runat="server" 104 Text="Modify State" Width="138px" />105 <br />106 <asp:RadioButton ID="EnterSharedRadioButton" runat="server" 107 Text="Enter Shared Scope" 108 AutoPostBack="true" /> <br />109 <br />110 <asp:Button ID="Toggle_Scope_Button" OnClick="Toggle_Scope_Button_Click" runat="server"111 Text="Change Scope" Width="186px" /><br />112 <br />113 <asp:Button ID="Reset_User_Button" OnClick="Reset_CurrentState_Button_Click" runat="server"114 Text="Reset Current Personalization" Width="185px" /></asp:Panel>115 116 </div>
最後少不了的就是在web.config中添加配置
在這裡開始吹水了,首先MSDN上面例子沒提及到要添加認證的配置,使得我最開始的時候登入了還沒看到效果。後來在懷疑是需要配置認證機制。接著這裡使用了一個Provider,AspNetSqlPersonalizationProvider並非類名,只是SqlPersonalizationProvider配置的名稱而已。預設配置如下,
在ASP.NET中實現了這個個人化提供者的就只有這個SqlPersonalizationProvider,這個我是看源碼還有MSDN中類的繼承結構中看出來的。不知有無其他地方明確指出,如需要其他的提供機制,則需要自訂擴充了。
您可以從其中 PersonalizationProvider ,並提供僅在此類中定義的抽象方法的實現。 抽象方法處理專門與儲存和載入資料寫入物理資料存放區,以及資料存放區區管理。 自訂提供者必須能夠處理可區分的方式的個人化資訊 Shared 中的資料 User 資料。 此外,提供者必須段個人化資料頁以及按應用程式。
實現 PersonalizationProvider 緊密耦合的實現與 PersonalizationState 由於某些個人化提供者方法返回的執行個體 PersonalizationState的衍生類別。 為了便於開發自訂提供者, PersonalizationProvider 基類包括個人化邏輯和序列化/還原序列化邏輯,直接使用的預設實現WebPartPersonalization 類。 結果是,創作專門用於使用不同的資料存放區區的自訂提供只需要下列抽象方法的實現︰
- GetCountOfState -此方法需要能夠在資料庫中為提供的查詢參數的個人化資料行的數目進行計數。
- LoadPersonalizationBlobs -在給定路徑和使用者名稱的情況下,此方法從資料庫中載入兩個二進位大型物件 (Blob): 一個用於共用的資料,另一個用於使用者資料的 BLOB。 如果您提供的使用者名稱稱和路徑,則不需要 WebPartManager 控制項,用於訪問可以提供的使用者檔案名稱/路徑資訊的頁資訊。
- ResetPersonalizationBlob -在給定路徑和使用者名稱的情況下,此方法中刪除資料庫中相應的行。 如果您提供的使用者名稱稱和路徑,則不需要WebPartManager 控制項,用於訪問可以提供的使用者檔案名稱/路徑資訊的頁資訊。
- SavePersonalizationBlob --此方法在給定的路徑和使用者名稱稱,儲存對資料庫所提供的 BLOB。 如果您提供的使用者名稱稱和路徑,則不需要 WebPartManager 控制項,用於訪問可以提供的使用者檔案名稱/路徑資訊的頁資訊。
在所有這些方法中,如果只提供一個路徑,則表示正在操作頁上的共用的個人化資料。 如果使用者名稱和路徑傳遞到方法中,頁上的使用者個人化資料應得到處理。 情況下 LoadPersonalizationBlobs, ,應始終載入指定的路徑的共用的資料,並 (可選) 的路徑的使用者個人化資料也如果應載入的使用者名稱不是 null。
所有抽象方法旨在僅用於管理應用程式,在運行時不使用由 Web 組件基礎結構。 個人化提供者的實現的樣本,請參閱SqlPersonalizationProvider 類。
說了這麼多看看這個樣本的運行效果
經過登入之後就可以看到介面如上所示,點擊Change xxx Color就可以改變方塊的顏色,這些顏色設定是儲存到資料庫的,使用者可以在登出下次登入時扔看到這些設定,包括對面板的關閉和最小化操作。下面的面板是控制這些設定的範圍,一個是使用者個人的,一個是全域共用的。可以通過Change Scope去切換。這裡涉及到兩個方面內容,首先是資料儲存,資料存放區在Web程式預設建立的SqlServer資料庫中,與MemberShip的庫相同。個人資料的放在PersonalizationAllUsers裡面,Share的則放在PersonalizationPerUser中。所有的資料都並非直接存放在表中,作為通用儲存的話這是不可能的。
另外關於許可權控制的,在設定檔中的personalization/authorization配置節跟system.web/authorization的結構很相像,區別在於verbs,這裡用的值僅以下兩種。
對於擷取設定資訊是不阻攔的,但是需要更換範圍進入共用區時需要有enterSharedScope許可權,當需要更改任何一個範圍的資料時需要modeifyState。如果兩個許可權都被deny的話,使用者就只能傻傻地看了
personalization的結束到此完,接下來到transformers。這裡涉及到一個web組件串連的概念。不知我自己有否理解錯,這個web組件串連的雙方中提供資料的一方個人感覺就是一個資料來源。資料來源提供的資料可以給頁面上其他多個控制項使用,但是資料來源提供的資料格式不一定符合其他所有控制項,因此這裡就需要一個轉換器來適配雙方的差異,這就是適配器模式嘛!嗎?但是要是說多弄一個資料來源(或者叫Provider)的話,這樣的開銷比較大。那麼ASP.NET提供的轉換器就只有兩個RowToFieldTransformer和RowToParametersTransformer,如果需要其他的轉換就需要自己定義,還需要到設定檔中聲明一下這個轉換器,下面也是借鑒了一個MSDN的例子來嘗試一下通過一個行轉換到字串。
對於MSDN的例子我還是精簡了兩個控制項,大概可以看以下這裡建立了一個靜態Web組件串連,通過一個rowtostringtransformer進行轉換。這個連結的提供者是rowproviderwebpart的自訂webPart,另一個stringconsumerwebpart的自訂webpart。這些類都定義在App_Code檔案夾中,所以註冊命名空間的時候要注意一下
下面就是各個檔案的代碼IString
RowToStringTransformer
下面這兩個類是參考了MSDN的代碼,自己根據當前的情況改過一下,不然運行不了,但不知道有否改錯,使之背離願意
// This sample code creates a Web Parts control that acts as a provider // of row data. [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] public sealed class RowProviderWebPart : WebPart, IWebPartRow { private DataTable _table; public RowProviderWebPart() { _table = new DataTable(); DataColumn col = new DataColumn(); col.DataType = typeof(string); col.ColumnName = "Name"; _table.Columns.Add(col); col = new DataColumn(); col.DataType = typeof(string); col.ColumnName = "Address"; _table.Columns.Add(col); col = new DataColumn(); col.DataType = typeof(int); col.ColumnName = "ZIP Code"; _table.Columns.Add(col); DataRow row = _table.NewRow(); row["Name"] = "John Q. Public"; row["Address"] = "123 Main Street"; row["ZIP Code"] = 98000; _table.Rows.Add(row); } [ConnectionProvider("String123")] public IWebPartRow GetConnection() { return new RowProviderWebPart(); } public PropertyDescriptorCollection Schema { get { return TypeDescriptor.GetProperties(_table.DefaultView[0]); } } public void GetRowData(RowCallback callback) { foreach (var item in _table.DefaultView) { callback(item); } } } [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] public sealed class StringConsumerWebpart : WebPart { private IString _provider; private string _stringData; private void GetRowData(object rowData) { _stringData = rowData.ToString(); } protected override void OnPreRender(EventArgs e) { if (_provider != null) { _provider.GetStringValue(new StringCallback(GetRowData)); } } protected override void RenderContents(HtmlTextWriter writer) { if (!string.IsNullOrEmpty(_stringData)) { writer.Write(_stringData); writer.WriteBreak(); writer.WriteLine(); } else { writer.Write("No data"); } } [ConnectionConsumer("String123")] public void SetConnection(IString provider) { _provider = provider; } }
在調試的時候發現_provider.GetStringValue(new StringCallback(GetRowData));這行代碼最繞,嵌了幾個委託;另外有個有意思的地方就是get/set串連的時候,它使用了一個類似依賴注入的東西,Attribute的Display參數把Connection的get/set兩個方法配對,完全忽略方法的命名,可惜這個ConnectionConsumer和ConnectionProvider只能描述方法,不然可以用到屬性去。
差點忘了把Web.config的配置添加進去
最終結果如,就把Provider中的一個table的專成了一個字串。
webParts與Web組件