Базовые странички ASP.NET
На этой страничке я хотел рассказать о способах построения базовых страничек в ASP.NET/MONO. Базовая страничка - это такая страничка, которая отрабатывает при каждом реквесте любой странички сайта и выполняет общие действия для любой странички сайта в пределах текущего проекта. Например, устанавливает контекст ображения пользователя к сайту (залогиненный контекст или анонимный, к своей ли страничке обращается пользователь или к чужой - в социальных сетях. Иными словами такая страничка готовит некоторые бызовые основания для работы всех остальных страничек сайта.
Предположим страничка сайта условно разрезена на две части левая/правая или верхняя/нижняя. Каждая часть странички представляет собой с точки зрения ASP.NET-кода - один контрол левый или правый, верхний или нижний. Не будете же вы в каждом контроле устанавливать отдельно - аутентифицированный ли юзер, активирован ли он, если ли у него права находится на этой страничке? Ведь это все обращения в базу - и сколько такая страничка будет готовится Web-сервером, если на ней разположены 10-15 контролов, и каждый автономно ходит в базу и проверяет там права пользователя? Поэтому такой функционал, повторяемый множество раз - как в пределах одной и той же странички, так и в пределах разных страничек одного и того же сайта - принято выносить в общую часть всего сайта, которая и называется базовая страничка.
В зависимости от обстоятельств я применяю четыре способа построения базовых страничек:
- Иногда это классические базовые странички - от которых наследуется каждая страничка сайта, те код базовой странички вписывается на место строки 14
1: <%@ Page Language="VB" MasterPageFile="~/M1.master" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
2:
3: <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
4: ....
5: </asp:Content>
6:
7: Partial Class _Default
8: Inherits BasePage
9: ...
10: End Class
11:
12: Public Class BasePage
13: Inherits System.Web.UI.Page
14: ===> ... <===
15: End Class
- Иногда я делаю на каждой страничке вызов некой функции, в которую собран код базовой странички. В этом повторяющийся код ложится на место строки 28.
1: Partial Class _Default
2: Inherits System.Web.UI.Page
3:
4: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
5: Dim ObjectChecker As New CheckContext
6: ObjectChecker.CheckUserContext( _
7: AddressOf ErrorParametersUser, _
8: AddressOf TargetUserNotFound, _
9: AddressOf CurrUserNotFound, _
10: AddressOf CurrProfileNotFound, _
11: AddressOf TargetProfileNotFound, _
12: AddressOf RightToHimself, _
13: AddressOf LeftToHimself, _
14: AddressOf AdminToHimself, _
15: AddressOf AdminToLeftUser, _
16: AddressOf AdminToRightUser, _
17: AddressOf LeftToLeftUser, _
18: AddressOf RightToRightUser, _
19: AddressOf RightToLeftUser, _
20: AddressOf LeftToRightUser, _
21: AddressOf AnonToLeftUser, _
22: AddressOf AnonToRightUser)
23: ...
24: End Sub
25: End Class
26:
27: Public Class CheckContext
28: ===> ... <===
29: End Class
- Иногда это контролы, которые лежат на страничке - и все базовые операции выполняются в них - в этом случае код базовой странички ложится на место строки 25:
1: <%@ Master Language="VB" CodeFile="M2.master.vb" Inherits="M2" %>
2: <%@ Register Src="AdminLink.ascx" TagName="AdminLink" TagPrefix="uc1" %>
3:
4: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5:
6: <html xmlns="http://www.w3.org/1999/xhtml" >
7: <head runat="server">
8: <title>CMS <asp:Literal runat="server" Text="<%$ appSettings:RealURL%>"/></title>
9: </head>
10: <body >
11: <form id="form1" runat="server">
12: <uc1:AdminLink ID="AdminLink1" runat="server" />
13: <div>
14: <asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
15: </asp:contentplaceholder>
16: </div>
17: </form>
18: </body>
19: </html>
20:
21: <%@ Control Language="VB" AutoEventWireup="false" CodeFile="AdminLink.ascx.vb" Inherits="AdminLink" %>
22:
23: Partial Class AdminLink
24: Inherits System.Web.UI.UserControl
25: ===> ... <===
26: End Class
- И наконец последний вариант, когда разметка странички наследуется от Master.page. Тогда некоторую часть общего кода сайта кода можно вынести непосредственно в код Master.page - на место строки 11.
1: <%@ Master Language="VB" CodeFile="M1.master.vb" Inherits="M1" %>
2: <html xmlns="http://www.w3.org/1999/xhtml">
3: ...
4: </html>
5:
6: Partial Class M1
7: Inherits System.Web.UI.MasterPage
8:
9: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
10: If Not IsPostBack Then
11: ===> ... <===
12: End If
13: End Sub
14: End Class
На этой страничке я хотел обсудить шаблоны кода для каждого из четырех случаев и обсудить обстоятельства, когда выгоден тот или иной вариант построения базовой странички.
На мой взгляд первый и второй варианты - выгодны для социальных сетей, где:
- У страничек есть множество одинаковых параметров в URL которые надо всякий раз однообразно разбирать на каждой страничке
- Есть свои и чужие странички. На свои страничках можно все менять, на чужих только смотреть и/или комментировать.
Первый вариант от второго отличается техникой программирования. Если надо управлять видимостью отдельных элементов странички, то надо делать второй (сокращенный) ContextChecker (для второго варианта) или делать базовую страничку для контролов.
Например базовую страничку социальной сети Votpusk.ru я построил по первому принципу:
1: Imports Microsoft.VisualBasic
2: Imports System.Web.Security
3: Imports System
4: Imports System.Web
5: Imports System.Web.Profile
6:
7: ''' <summary>
8: ''' Это базовый класс сайта, добавляюющий к стандартному классу странички пару свойств
9: ''' Иcпользуется на всех персональных страничках (при постбеках и нет) - где требуется эта проверка корректности номера юзера (к кому заходим), заданного в Request.QueryString("i")
10: ''' Просто определить тут WEB-контролы низзя - перестанут работать все диалоговые инструменты студии и привязки в SqlDataSource
11: ''' </summary>
12: '''
13: Public Class VotpuskBasePage
14: Inherits System.Web.UI.Page
15: ''' <summary>
16: ''' Это ссылка на шифровалку параметров
17: ''' </summary>
18: Public ReadOnly Property PP8() As vbnet2009.ParmProtector8
19: Get
20: Return CType(Application("ParmProtector8"), vbnet2009.ParmProtector8)
21: End Get
22: End Property
23:
24: Dim _TypeOfPageLoad As Votpusk.RequestType
25: ''' <summary>
26: ''' Это тип загрузки странички этого сайта
27: ''' </summary>
28: Public ReadOnly Property QueryString_TypeOfPageLoad() As Votpusk.RequestType
29: Get
30: Return _TypeOfPageLoad
31: End Get
32: End Property
33:
34: Dim _ToUser As MembershipUser
35: ''' <summary>
36: ''' К какому юзеру входим по QueryString (рассчитывается функцией CheckRequest)
37: ''' </summary>
38: Public ReadOnly Property QueryString_I_User() As MembershipUser
39: Get
40: Return _ToUser
41: End Get
42: End Property
43:
44: Dim _ToUserProfile As ProfileCommon
45: ''' <summary>
46: ''' Это профиль юзера к которому заходим по Querystring
47: ''' </summary>
48: Public ReadOnly Property QueryString_I_UserProfile() As ProfileCommon
49: Get
50: Return _ToUserProfile
51: End Get
52: End Property
53:
54: Dim _FromUserProfile As ProfileCommon
55: ''' <summary>
56: ''' Это профиль AU юзера, который заходит
57: ''' </summary>
58: Public ReadOnly Property QueryString_AU_From_UserProfile() As ProfileCommon
59: Get
60: Return _FromUserProfile
61: End Get
62: End Property
63:
64: Dim _QueryString_I_UserName As String
65: ''' <summary>
66: ''' Имя юзера к кому зашли по QueryString
67: ''' </summary>
68: Public ReadOnly Property QueryString_I_UserName() As String
69: Get
70: Return _QueryString_I_UserName
71: End Get
72: End Property
73:
74: Dim _QueryString_g As String
75: ''' <summary>
76: ''' QueryString("g") в расшифрованном виде
77: ''' </summary>
78: Public ReadOnly Property QueryString_g() As String
79: Get
80: Return _QueryString_g
81: End Get
82: End Property
83:
84: Dim _QueryString_t As String
85: ''' <summary>
86: ''' QueryString("t") в расшифрованном виде
87: ''' </summary>
88: Public ReadOnly Property QueryString_t() As String
89: Get
90: Return _QueryString_t
91: End Get
92: End Property
93:
94: Dim _QueryString_j As String
95: ''' <summary>
96: ''' QueryString("j") в расшифрованном виде
97: ''' </summary>
98: Public ReadOnly Property QueryString_j() As String
99: Get
100: Return _QueryString_j
101: End Get
102: End Property
103:
104: ''' <summary>
105: ''' Для определения нового контента
106: ''' </summary>
107: Public ReadOnly Property OldContentCounter() As Votpusk.SiteContentCount
108: Get
109: Return CType(Session("OldContentCounter"), Votpusk.SiteContentCount)
110: End Get
111: End Property
112:
113: Private Sub VotpuskBasePage_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
114: 'сначала заполнили базовые свойства странички _ToUser,TypeOfPageLoad
115: Session("CheckRequest") = CheckRequest(IsPostBack)
116: _TypeOfPageLoad = CType(Session("CheckRequest"), Votpusk.RequestType)
117: If _ToUser IsNot Nothing Then _QueryString_I_UserName = _ToUser.UserName
118: 'теперь, если в Querystring заданы g, t, j - впишем их в hidentype-контролы странички в расшифрованном виде
119: If Request.QueryString("g") <> "" Then _QueryString_g = vbnet2009.PP8_Helper.Unmask_QueryString("g", "SQLServer_ConnectionStrings") 'номер в табле GroupName
120: If Request.QueryString("t") <> "" Then _QueryString_t = vbnet2009.PP8_Helper.Unmask_QueryString("t", "SQLServer_ConnectionStrings") 'номер в табле LoadType
121: If Request.QueryString("j") <> "" Then _QueryString_j = vbnet2009.PP8_Helper.Unmask_QueryString("j", "SQLServer_ConnectionStrings") 'номер в табле UserData
122: End Sub
123:
124: ''' <summary>
125: ''' Проверка типа входа - к себе/не к себе.
126: ''' Отрезает совсем левые входы с подделанным или пустым номером юзера
127: ''' </summary>
128: Private Function CheckRequest(ByVal IsPostback As Boolean) As Votpusk.RequestType
129: If HttpContext.Current.Request.QueryString("i") = "" Then
130: If HttpContext.Current.User.Identity.IsAuthenticated Then
131: 'аутентифицированного юзера перенаправляем к себе же на страничку
132: My.Log.WriteEntry("1. Error. Не задан QueryString('i'). Аутентифицированного юзера перенаправляем к себе же на страничку. IsPostback=" & IsPostback.ToString)
133: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].UserHomePage)
134: Else
135: 'левый вход непонятно кого и непонятно к кому
136: My.Log.WriteEntry("2. Error. Не задан QueryString('i'). Левый вход неаутентифицированного непонятно к кому. Направляем на NotSupported. IsPostback=" & IsPostback.ToString)
137: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].NotSupported & "?ErrorMessage=""Не задан QueryString('i'). Левый вход неаутентифицированного непонятно к кому""&URL=""" & Request.RawUrl & """")
138: End If
139: Else
140: 'вход к конкретно заданному юзеру
141: Try
142: Dim ToGuid As New Guid(HttpContext.Current.Request.QueryString("i"))
143: If Membership.GetUser(ToGuid) Is Nothing Then
144: If HttpContext.Current.User.Identity.IsAuthenticated Then
145: 'аутентифицированного юзера перенаправляем к себе же на страничку
146: My.Log.WriteEntry("3. Error. Не найден юзер по заданному GUID. Аутентифицированного юзера перенаправляем к себе же на страничку. IsPostback=" & IsPostback.ToString)
147: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].UserHomePage)
148: Else
149: 'левый вход непонятно кого и непонятно к кому
150: My.Log.WriteEntry("4. Error. Не получилось сделать GUID по заданному QueryString('i'). " & HttpContext.Current.Request.QueryString("i") & " Левый вход неаутентифицированного непонятно к кому. Направляем на NotSupported. IsPostback=" & IsPostback.ToString)
151: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].NotSupported & "?ErrorMessage=""Не получилось сделать GUID по заданному QueryString('i')""&URL=""" & Request.RawUrl & """")
152: End If
153: Else
154: 'запрошенный юзер СУЩЕСТВУЕТ - идем дальше
155: _ToUser = Membership.GetUser(ToGuid)
156: End If
157: Catch ex As Exception
158: If HttpContext.Current.User.Identity.IsAuthenticated Then
159: 'аутентифицированного юзера перенаправляем к себе же на страничку
160: My.Log.WriteEntry("5. Error. Не получилось сделать GUID по заданному QueryString('i') =" & HttpContext.Current.Request.QueryString("i") & " Аутентифицированного юзера перенаправляем к себе же на страничку. IsPostback=" & IsPostback.ToString)
161: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].UserHomePage)
162: Else
163: 'левый вход непонятно кого и непонятно к кому
164: My.Log.WriteEntry("6. Error. Не получилось сделать GUID по заданному QueryString('i'). " & HttpContext.Current.Request.QueryString("i") & " Левый вход неаутентифицированного непонятно к кому. Направляем на NotSupported. IsPostback=" & IsPostback.ToString)
165: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].NotSupported & "?ErrorMessage=""Не получилось сделать GUID по заданному QueryString('i')""&URL=""" & Request.RawUrl & """")
166: End If
167: End Try
168: '
169: If _ToUser Is Nothing Then
170: My.Log.WriteEntry("7. Error. Так и не получили имени юзера по QueryString('i') =" & HttpContext.Current.Request.QueryString("i") & " Аутентифицированного юзера перенаправляем к себе же на страничку. IsPostback=" & IsPostback.ToString)
171: 'аутентифицированного юзера перенаправляем к себе же на страничку
172: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].UserHomePage)
173: End If
174: '
175: Try
176: _ToUserProfile = ProfileBase.Create(_ToUser.UserName)
177: Catch ex As Exception
178: My.Log.WriteEntry("8. Error. Не прочитался профиль юзера " & HttpContext.Current.Request.QueryString("i"))
179: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].NotSupported & "?ErrorMessage=""Не прочитался профиль юзера ""&URL=""" & Request.RawUrl & """")
180: End Try
181: '
182: If HttpContext.Current.User.Identity.IsAuthenticated Then
183: _FromUserProfile = ProfileBase.Create(HttpContext.Current.User.Identity.Name)
184: If _FromUserProfile IsNot Nothing Then
185: If HttpContext.Current.Request.QueryString("i") = Membership.GetUser(HttpContext.Current.User.Identity.Name).ProviderUserKey.ToString Then
186: My.Log.WriteEntry("AuUserToHimself. Аутентифицированный юзер '" & HttpContext.Current.User.Identity.Name & "' зашел к себе. IsPostback=" & IsPostback.ToString)
187: If _FromUserProfile.LoginIsActivate Then
188: Return Votpusk.RequestType.ActiveUserToHimself
189: Else
190: Return Votpusk.RequestType.InActiveUserToHimself
191: End If
192: Else
193: If _ToUserProfile.LoginIsActivate Then
194: My.Log.WriteEntry("AuUserToOtherActive. Аутентифицированный юзер '" & HttpContext.Current.User.Identity.Name & "' зашел на страничку другого юзера " & HttpContext.Current.Request.QueryString("i") & " c активированным логином. IsPostback=" & IsPostback.ToString)
195: If _FromUserProfile.LoginIsActivate Then
196: Return Votpusk.RequestType.ActiveToOtherActive
197: Else
198: Return Votpusk.RequestType.InActiveToOtherActive
199: End If
200: Else
201: My.Log.WriteEntry("AuUserToOtherInActive. Аутентифицированный юзер '" & HttpContext.Current.User.Identity.Name & "' зашел на страничку другого юзера " & HttpContext.Current.Request.QueryString("i") & " c Неактивированным логином. IsPostback=" & IsPostback.ToString)
202: If _FromUserProfile.LoginIsActivate Then
203: Return Votpusk.RequestType.ActiveToOtherInActive
204: Else
205: Return Votpusk.RequestType.InActiveToOtherInActive
206: End If
207: End If
208: End If
209: Else
210: My.Log.WriteEntry("8-1. Error. Не прочитался профиль юзера " & HttpContext.Current.User.Identity.Name)
211: HttpContext.Current.Response.Redirect(Votpusk.[GoTo].NotSupported & "?ErrorMessage=""Не прочитался профиль юзера ""&Login=""" & HttpContext.Current.User.Identity.Name & """")
212: End If
213: Else
214: If _ToUserProfile.LoginIsActivate Then
215: My.Log.WriteEntry("AnonUserToActive. Неаутифицированный юзер зашел посмотреть страничку конкретного юзера " & HttpContext.Current.Request.QueryString("i") & " c активированным логином. IsPostback=" & IsPostback.ToString)
216: Return Votpusk.RequestType.AnonUserToActive
217: Else
218: My.Log.WriteEntry("AnonUserToInActive. Неаутифицированный юзер зашел посмотреть страничку конкретного юзера " & HttpContext.Current.Request.QueryString("i") & " c Неактивированным логином. IsPostback=" & IsPostback.ToString)
219: Return Votpusk.RequestType.AnonUserToInActive
220: End If
221: End If
222: End If
223: End Function
224: End Class
Как видите, тут содержатся ссылки на важные классы (для шифрования параметров), параметры странички в расшифрованном виде, проверятся куда заходит юзер - к себе/не к себе. При заведомо поддельных параметрах - такой хитрый юзер отфутболивается на странички с ошибками. Странички с ошибками должны быть тупиковыми - на них нет ссылок. Таким образом паук, автоматически обходящий сайт - заводится в тупик.
В таком варианте построения базовых страничек каждая страничка содержит примерно вот такую гирлянду кода:
1: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
2: If Not IsPostBack Then
3: Select Case QueryString_TypeOfPageLoad
4: Case Votpusk.RequestType.AnonUserToActive
5: Response.Redirect(Votpusk.[GoTo].WarningPage)
6: Case Votpusk.RequestType.ActiveUserToHimself, Votpusk.RequestType.InActiveUserToHimself
7: CurrPageState = CType(Session("PageState"), Votpusk.PageState)
8: If CurrPageState.ContactAll_PageState = 0 Then
9: CommentLabel1.Text = "Конструктор группировки моих контактов."
10: MultiView1.ActiveViewIndex = 0
11: GridView1.DataBind()
12: Else
13: CommentLabel1.Text = "Мои контакты."
14: MultiView1.ActiveViewIndex = 2
15: GridView2.DataBind()
16: End If
17: Case Votpusk.RequestType.ActiveToOtherActive, Votpusk.RequestType.InActiveToOtherActive
18: Response.Redirect(Votpusk.[GoTo].NotSupported & "?ErrorMessage=""Левый вход не к себе.""&URL=""" & Request.RawUrl & """")
19: Case Votpusk.RequestType.ActiveToOtherInActive, Votpusk.RequestType.InActiveToOtherInActive
20: MultiView1.ActiveViewIndex = 1
21: Case Votpusk.RequestType.AnonUserToInActive
22: MultiView1.ActiveViewIndex = 1
23: End Select
24: End If
Те при загрузке каждой странички надо сделать ветвление в Page_Load в зависимости от контекста загрузки - который выставляется на базовой страничке - анонимный юзер, администратор, на своей страничке, на чужой и так далее. Кроме контекста базовая страничка дает основному рабочему коду уже расшифрованные параметры и другие важные ссылки, многократно используемые на страничке.
Второй способ - он немного отличается от первого способа, когда код разбора контекста реквеста выполняется до собственно создания конкретной странички MyPage.aspx. Во втором способе страничка создается нормально, наследуюя System.Web.UI.Page, однако в Page_Load каждой странички встраивается вызов проверки контекста вызова странички.
Эта техника тоже идальна для социальных сетей, однако я ее применяю когда странички сложные и легко запутаться какой именно элемент (например кнопка Удалить или кнопка Комментировать) - должен быть показан в том или ином контексте загрузки. Например, находясь на чужой страничке - можно только комментировать, на своей - можно только удалить, а админ сайта - может забанить/разбанить контент любой странички. Например, в моем сайте http://arenda.votpusk.ru/ на страничках очень много всяких кнопок, чекобоксов и прочих элементов, которые должны показываться (или не показываться) по-разному - в зависимости от шестнадцатразличных контекстов вызова странички. Чтобы не запутаться в 16-ти ветвлениях в огромном SELECT CASE в Page_Load я сделал в этом проекте вот такую базовую страничку (часть):
1: Imports Microsoft.VisualBasic
2:
3: Public Enum TypeOfPageLoad
4: AdminToHimself = 1
5: RightToHimself = 2
6: LeftToHimself = 3
7: AdminToLeftUser = 4
8: AdminToRightUser = 5
9: LeftToLeftUser = 6
10: RightToRightUser = 7
11: RightToLeftUser = 8
12: LeftToRightUser = 9
13: AnonToLeftUser = 10
14: AnonToRightUser = 11
15: LegalAnonContext = 12
16: ErrContext = 13
17: AdminContext = 14
18: RightUserContext = 15
19: LeftUserContext = 16
20: CurrUserNotFound = 17
21: ProfileNotFound = 18
22: End Enum
23:
24: ''' <summary>
25: ''' Проверка свой/чужой контекст, залогиненный/незалогиненный юзер - просто для контекста и для обьекта
26: ''' </summary>
27: Public Class CheckContext
28:
29: Public Delegate Sub AU_Callback(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon, ByVal ObjectOwner As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
30: Public Delegate Sub Himself_Callback(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile As ProfileCommon)
31: Public Delegate Sub Anon_Callback(ByVal ObjectOwner As MembershipUser, ByVal MyTypedProfile As ProfileCommon)
32: Public Delegate Sub ErrCalback()
33: Public Delegate Sub User_Callback(ByVal User As MembershipUser, ByVal MyTypedProfile As ProfileCommon)
34: Public Delegate Sub User_To_User_Callback(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon, ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
35:
36:
37: ''' <summary>
38: ''' Запрос на чтение владельца обьекта
39: ''' </summary>
40: Public ReadOnly Property SelectObjectOwnerQuery() As String
41: Get
42: Return _SelectObjectOwnerQuery
43: End Get
44: End Property
45: Dim _SelectObjectOwnerQuery As String = "select ToUser from [Objects] with (nolock) where ID=@Object_ID"
46:
47:
48: ''' <summary>
49: ''' Определение контекста вызова странички
50: ''' </summary>
51: ''' <param name="AdminContext">вход администратора</param>
52: ''' <param name="RightUserContext"> вход зарегистрированного, активированного юзера</param>
53: ''' <param name="LeftUserContext">вход зарегистрированного, но неактивированного юзера</param>
54: ''' <param name="LegalAnonContext">анонимный вызов этой странички </param>
55: ''' <param name="CurrUserNotFound">не найден в Membership текущий залогиненный юзер</param>
56: ''' <param name="ProfileNotFound">отсутсвует профиль залогиненного пользователя</param>
57: ''' <remarks></remarks>
58: Public Sub CheckCurrentContext( _
59: ByVal AdminContext As Himself_Callback, _
60: ByVal RightUserContext As Himself_Callback, _
61: ByVal LeftUserContext As Himself_Callback, _
62: ByVal LegalAnonContext As ErrCalback, _
63: ByVal CurrUserNotFound As ErrCalback, _
64: ByVal ProfileNotFound As ErrCalback)
65: '
66: If HttpContext.Current.User.Identity.IsAuthenticated Then
67: 'залогиненный контекст
68: Dim CurrentUser As MembershipUser = Membership.GetUser(HttpContext.Current.User.Identity.Name)
69: If CurrentUser IsNot Nothing Then
70: '
71: If Roles.IsUserInRole("UserAdmin") Then
72: 'контекст администратора
73: Dim CurrentUserProfile As ProfileCommon = ReadMyTypedProfile(CurrentUser, ProfileNotFound)
74: If CurrentUserProfile Is Nothing Then Exit Sub
75: AdminContext.Invoke(CurrentUser, CurrentUserProfile)
76: Else
77: 'залогиненный контекст простого юзера
78: Dim CurrentUserProfile As ProfileCommon = ReadMyTypedProfile(CurrentUser, ProfileNotFound)
79: If CurrentUserProfile Is Nothing Then Exit Sub
80: '
81: If CurrentUserProfile.LoginIsActivate Then
82: 'этот пользователь уже авторизован
83: RightUserContext.Invoke(CurrentUser, CurrentUserProfile)
84: Else
85: 'только что зарегистировавался
86: LeftUserContext.Invoke(CurrentUser, CurrentUserProfile)
87: End If
88: End If
89: Else
90: 'не найден юзер
91: CurrUserNotFound.Invoke()
92: End If
93: Else
94: 'незалогиненный контекст
95: LegalAnonContext.Invoke()
96: End If
97: End Sub
98:
99:
100: ''' <summary>
101: ''' Определение контекста вызова странички при указании в QueryString номера пользователя
102: ''' </summary>
103: ''' <param name="ErrorParametersUser">Ошибка параметра Querystring("User")</param>
104: ''' <param name="TargetUserNotFound">Нет юзера к которому заходим</param>
105: ''' <param name="CurrUserNotFound">отсутвует в Membership текущий юзер</param>
106: ''' <param name="CurrProfileNotFound">нет профиля текущего юзера</param>
107: ''' <param name="TargetProfileNotFound">нет профиля юзера, чья страничка вызвана</param>
108: ''' <param name="RightToHimself">активированный залогиненный юзер зашел к себе на страничку</param>
109: ''' <param name="LeftToHimself">неактивированный залогиненный юзер зашел к себе на страничку</param>
110: ''' <param name="AdminToHimself">админ зашел на свою страничку</param>
111: ''' <param name="AdminToLeftUser">админ зашел к неактивированному юзеру</param>
112: ''' <param name="AdminToRightUser">админ зашел к активированному юзеру</param>
113: ''' <param name="LeftToLeftUser">неактивированный залогиненный юзер зашел на страничку к неактивированному</param>
114: ''' <param name="RightToRightUser">активированный залогиненный юзер зашел на страничку к активированному юзеру</param>
115: ''' <param name="RightToLeftUser">активированный залогиненный юзер зашел на страничку к неактивированному юзеру</param>
116: ''' <param name="LeftToRightUser">активированный залогиненный юзер зашел на страничку к неактивированному</param>
117: ''' <param name="AnonToLeftUser">аноним зашел к неактивированному юзеру</param>
118: ''' <param name="AnonToRightUser">аноним зашел к активированному юзеру</param>
119: ''' <remarks></remarks>
120: Public Sub CheckUserContext(ByVal ErrorParametersUser As ErrCalback, _
121: ByVal TargetUserNotFound As ErrCalback, _
122: ByVal CurrUserNotFound As ErrCalback, _
123: ByVal CurrProfileNotFound As ErrCalback, _
124: ByVal TargetProfileNotFound As ErrCalback, _
125: ByVal RightToHimself As User_Callback, _
126: ByVal LeftToHimself As User_Callback, _
127: ByVal AdminToHimself As User_Callback, _
128: ByVal AdminToLeftUser As User_To_User_Callback, _
129: ByVal AdminToRightUser As User_To_User_Callback, _
130: ByVal LeftToLeftUser As User_To_User_Callback, _
131: ByVal RightToRightUser As User_To_User_Callback, _
132: ByVal RightToLeftUser As User_To_User_Callback, _
133: ByVal LeftToRightUser As User_To_User_Callback, _
134: ByVal AnonToLeftUser As User_Callback, _
135: ByVal AnonToRightUser As User_Callback)
136:
137: If HttpContext.Current.Request.QueryString("User") Is Nothing Then
138: ErrorParametersUser.Invoke()
139: Exit Sub
140: End If
141: If HttpContext.Current.Request.QueryString("User") = "" Then
142: ErrorParametersUser.Invoke()
143: Exit Sub
144: End If
145: Dim UserID As String = HttpContext.Current.Request.QueryString("User")
146: Try
147: 'это просто проверка того, что сюда суют именно GUID
148: Dim Guid1 As Guid = New Guid(UserID)
149: Catch ex As Exception
150: ErrorParametersUser.Invoke()
151: Exit Sub
152: End Try
153: '
154: Dim TargetUser As MembershipUser
155: TargetUser = Membership.GetUser(New Guid(UserID))
156: If TargetUser Is Nothing Then
157: TargetUserNotFound.Invoke()
158: Exit Sub
159: End If
160: Dim MyTypedProfile_Target As ProfileCommon = ReadMyTypedProfile(TargetUser, TargetProfileNotFound)
161: '
162: Dim CurrentUser As MembershipUser
163: If HttpContext.Current.User.Identity.IsAuthenticated Then
164: CurrentUser = Membership.GetUser(HttpContext.Current.User.Identity.Name)
165: If CurrentUser Is Nothing Then
166: CurrUserNotFound.Invoke()
167: Exit Sub
168: End If
169: Dim MyTypedProfile_Current As ProfileCommon = ReadMyTypedProfile(CurrentUser, CurrProfileNotFound)
170: Dim IsAdmin As Boolean = Roles.IsUserInRole(CurrentUser.UserName, "UserAdmin")
171: If CurrentUser.UserName = TargetUser.UserName Then
172: 'зашел к себе на страничку
173: If IsAdmin Then
174: AdminToHimself.Invoke(CurrentUser, MyTypedProfile_Current)
175: Else
176: If MyTypedProfile_Current.LoginIsActivate Then
177: RightToHimself.Invoke(CurrentUser, MyTypedProfile_Current)
178: Else
179: LeftToHimself.Invoke(CurrentUser, MyTypedProfile_Current)
180: End If
181: End If
182: Else
183: 'зашел на чужую страничку
184: If IsAdmin Then
185: If MyTypedProfile_Target.LoginIsActivate Then
186: AdminToRightUser.Invoke(CurrentUser, MyTypedProfile_Current, TargetUser, MyTypedProfile_Target)
187: Else
188: AdminToLeftUser.Invoke(CurrentUser, MyTypedProfile_Current, TargetUser, MyTypedProfile_Target)
189: End If
190: Else
191: If MyTypedProfile_Current.LoginIsActivate Then
192: If MyTypedProfile_Target.LoginIsActivate Then
193: RightToRightUser(CurrentUser, MyTypedProfile_Current, TargetUser, MyTypedProfile_Target)
194: Else
195: RightToLeftUser(CurrentUser, MyTypedProfile_Current, TargetUser, MyTypedProfile_Target)
196: End If
197: Else
198: If MyTypedProfile_Target.LoginIsActivate Then
199: LeftToRightUser(CurrentUser, MyTypedProfile_Current, TargetUser, MyTypedProfile_Target)
200: Else
201: LeftToLeftUser(CurrentUser, MyTypedProfile_Current, TargetUser, MyTypedProfile_Target)
202: End If
203: End If
204: End If
205: End If
206: Else
207: 'аноним зашел к кому-то
208: If MyTypedProfile_Target.LoginIsActivate Then
209: AnonToRightUser.Invoke(TargetUser, MyTypedProfile_Target)
210: Else
211: AnonToLeftUser.Invoke(TargetUser, MyTypedProfile_Target)
212: End If
213: End If
214: End Sub
215:
216:
217:
218: ''' <summary>
219: ''' Определение контекста вызова странички при указании в Querystring номера Обьекта недвижимости
220: ''' </summary>
221: ''' <param name="ErrorParametersObject_ID">В параметрах передан не GUID</param>
222: ''' <param name="ObjectNotFound">Объект не найден</param>
223: ''' <param name="UserOwnerNotFound">не найден юзер - владелец обьекта</param>
224: ''' <param name="CurrUserNotFound">не найден в Membership текущий залогиненный юзер</param>
225: ''' <param name="ProfileNotFound">нету профиля залогиненного юзера</param>
226: ''' <param name="RightToHimself">зарегистрированный активированный юзер зашел к себе</param>
227: ''' <param name="LeftToHimself">зарегистрированный неактивированный юзер зашел к себе<</param>
228: ''' <param name="AdminToHimself">администратор зашел к себе</param>
229: ''' <param name="AdminToLeftUser">администратор зашел к неавторизованному юзеру</param>
230: ''' <param name="AdminToRightUser">администратор зашел к авторизованному юзеру</param>
231: ''' <param name="LeftToLeftUser">неактивированный залогиненный юзер зашел к другому неактивированному</param>
232: ''' <param name="RightToRightUser">зарегистрированный активированный юзер зашел к другому активированному зарегистрированному юзеру</param>
233: ''' <param name="RightToLeftUser">зарегистрированный активированный юзер зашел к другому зарегистрированному неактивированному юзеру</param>
234: ''' <param name="LeftToRightUser">зарегистрированный неактивированный юзер зашел к другому зарегистрированному активированному юзеру</param>
235: ''' <param name="AnonToLeftUser">аноним зашел к зарегистрированный неактивированному юзеру</param>
236: ''' <param name="AnonToRightUser">аноним зашел к зарегистрированный активированному юзеру</param>
237: ''' <remarks></remarks>
238: Public Sub CheckObjectContext(ByVal ErrorParametersObject_ID As ErrCalback, _
239: ByVal ObjectNotFound As ErrCalback, _
240: ByVal UserOwnerNotFound As ErrCalback, _
241: ByVal CurrUserNotFound As ErrCalback, _
242: ByVal ProfileNotFound As ErrCalback, _
243: ByVal RightToHimself As Himself_Callback, _
244: ByVal LeftToHimself As Himself_Callback, _
245: ByVal AdminToHimself As Himself_Callback, _
246: ByVal AdminToLeftUser As AU_Callback, _
247: ByVal AdminToRightUser As AU_Callback, _
248: ByVal LeftToLeftUser As AU_Callback, _
249: ByVal RightToRightUser As AU_Callback, _
250: ByVal RightToLeftUser As AU_Callback, _
251: ByVal LeftToRightUser As AU_Callback, _
252: ByVal AnonToLeftUser As Anon_Callback, _
253: ByVal AnonToRightUser As Anon_Callback)
254:
255:
256: If HttpContext.Current.Request.QueryString("Object") Is Nothing Then
257: ErrorParametersObject_ID.Invoke()
258: Exit Sub
259: End If
260: If HttpContext.Current.Request.QueryString("Object") = "" Then
261: ErrorParametersObject_ID.Invoke()
262: Exit Sub
263: End If
264: Dim Object_ID As String = HttpContext.Current.Request.QueryString("Object")
265: Try
266: 'это просто проверка того, что сюда суют именно GUID
267: Dim Guid1 As Guid = New Guid(Object_ID)
268: Catch ex As Exception
269: ErrorParametersObject_ID.Invoke()
270: Exit Sub
271: End Try
272: '
273: Dim ObjectOwnerUser As MembershipUser = GetObjectOwner(Object_ID, ObjectNotFound, UserOwnerNotFound)
274: If ObjectOwnerUser Is Nothing Then Exit Sub
275: '
276: Dim OwnerUserProfile As ProfileCommon = ReadMyTypedProfile(ObjectOwnerUser, ProfileNotFound)
277: If OwnerUserProfile Is Nothing Then Exit Sub
278: '
279: If HttpContext.Current.User.Identity.IsAuthenticated Then
280: 'залогиненный контекст
281: Dim CurrentUser As MembershipUser = Membership.GetUser(HttpContext.Current.User.Identity.Name)
282: If CurrentUser IsNot Nothing Then
283: '
284: Dim CurrentUserProfile As ProfileCommon = ReadMyTypedProfile(CurrentUser, ProfileNotFound)
285: If CurrentUserProfile Is Nothing Then Exit Sub
286: '
287: If Roles.IsUserInRole("UserAdmin") Then
288: 'контекст администратора
289: If ObjectOwnerUser.ProviderUserKey = CurrentUser.ProviderUserKey Then
290: 'у себя
291: AdminToHimself.Invoke(CurrentUser, OwnerUserProfile)
292: Else
293: 'у другого юзера
294: If OwnerUserProfile.LoginIsActivate Then
295: 'у авторизовавшегося
296: AdminToRightUser.Invoke(CurrentUser, CurrentUserProfile, ObjectOwnerUser, OwnerUserProfile)
297: Else
298: 'у только что зарегистировавшегося
299: AdminToLeftUser.Invoke(CurrentUser, CurrentUserProfile, ObjectOwnerUser, OwnerUserProfile)
300: End If
301: End If
302: Else
303: 'залогиненный контекст простого юзера
304: If ObjectOwnerUser.ProviderUserKey = CurrentUser.ProviderUserKey Then
305: 'у себя
306: '
307: If CurrentUserProfile.LoginIsActivate Then
308: 'этот пользователь уже авторизован
309: RightToHimself.Invoke(CurrentUser, CurrentUserProfile)
310: Else
311: 'только что зарегистировавался
312: LeftToHimself.Invoke(CurrentUser, CurrentUserProfile)
313: End If
314: Else
315: 'у другого юзера
316: '
317: If OwnerUserProfile.LoginIsActivate Then
318: 'у авторизовавшегося
319: If CurrentUserProfile.LoginIsActivate Then
320: RightToRightUser.Invoke(CurrentUser, CurrentUserProfile, ObjectOwnerUser, OwnerUserProfile)
321: Else
322: LeftToRightUser.Invoke(CurrentUser, CurrentUserProfile, ObjectOwnerUser, OwnerUserProfile)
323: End If
324: Else
325: 'у только что зарегистировавшегося
326: If CurrentUserProfile.LoginIsActivate Then
327: RightToLeftUser.Invoke(CurrentUser, CurrentUserProfile, ObjectOwnerUser, OwnerUserProfile)
328: Else
329: LeftToLeftUser.Invoke(CurrentUser, CurrentUserProfile, ObjectOwnerUser, OwnerUserProfile)
330: End If
331: End If
332: End If
333: End If
334: Else
335: 'не найден юзер
336: CurrUserNotFound.Invoke()
337: End If
338: Else
339: 'незалогиненный контекст
340: If OwnerUserProfile.LoginIsActivate Then
341: AnonToRightUser(ObjectOwnerUser, OwnerUserProfile)
342: Else
343: AnonToLeftUser.Invoke(ObjectOwnerUser, OwnerUserProfile)
344: End If
345: End If
346: End Sub
347:
348: ...
В такой архитектуре вначале каждой странички просто делается проверка контекста юзера (CheckUserContext) или проверка контекста просмотра обьекта (CheckObjectContext) - в ВСЯ страничка просто состоит из делегатов, в которых выполняется управление элементами странички:
1: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
2: Dim ObjectChecker As New CheckContext
3: ObjectChecker.CheckUserContext( _
4: AddressOf ErrorParametersUser, _
5: AddressOf TargetUserNotFound, _
6: AddressOf CurrUserNotFound, _
7: AddressOf CurrProfileNotFound, _
8: AddressOf TargetProfileNotFound, _
9: AddressOf RightToHimself, _
10: AddressOf LeftToHimself, _
11: AddressOf AdminToHimself, _
12: AddressOf AdminToLeftUser, _
13: AddressOf AdminToRightUser, _
14: AddressOf LeftToLeftUser, _
15: AddressOf RightToRightUser, _
16: AddressOf RightToLeftUser, _
17: AddressOf LeftToRightUser, _
18: AddressOf AnonToLeftUser, _
19: AddressOf AnonToRightUser)
20:
21: ....
22:
23: End Sub
24:
25: #Region "Доступность элементов странички в зависимости от контекста вызова странички"
26:
27: 'активированный залогиненный юзер зашел к себе на страничку
28: Sub RightToHimself(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon)
29: UserMenu1.MenuUser = CurrentUser
30: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.RightToHimself
31: ThisTypePageLoad = TypeOfPageLoad.RightToHimself
32:
33: End Sub
34:
35: Sub LeftToHimself(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon)
36: UserMenu1.MenuUser = CurrentUser
37: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.LeftToHimself
38: ThisTypePageLoad = TypeOfPageLoad.LeftToHimself
39: lErr1.Text = "Вы не можете добавлять новые объекты пока не прошли активацию"
40: End Sub
41:
42: 'ошибка параметра Querystring("User")
43: Sub ErrorParametersUser()
44: UserMenu1.Visible = False
45: lErr1.Text = "Ошибка. Пользователь не найден."
46: 'AddLink1.Visible = False
47: End Sub
48:
49: 'админ зашел на свою страничку
50: Sub AdminToHimself(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon)
51: UserMenu1.MenuUser = CurrentUser
52: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.AdminToHimself
53: ThisTypePageLoad = TypeOfPageLoad.AdminToHimself
54: End Sub
55:
56: 'админ зашел к неактивированному юзеру
57: Sub AdminToLeftUser(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon, ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
58: UserMenu1.MenuUser = TargetUser
59: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.AdminToLeftUser
60: ThisTypePageLoad = TypeOfPageLoad.AdminToLeftUser
61: lErr1.Text = "Этот пользователь еще не прошел активацию и не может добавлять свои объекты"
62: End Sub
63:
64: 'админ зашел к активированному юзеру
65: Sub AdminToRightUser(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon, ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
66: UserMenu1.MenuUser = TargetUser
67: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.AdminToRightUser
68: ThisTypePageLoad = TypeOfPageLoad.AdminToRightUser
69: End Sub
70:
71: 'неактивированный залогиненный юзер зашел на страничку к неактивированному
72: Sub LeftToLeftUser(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon, ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
73: UserMenu1.MenuUser = TargetUser
74: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.LeftToLeftUser
75: ThisTypePageLoad = TypeOfPageLoad.LeftToLeftUser
76: lErr1.Text = "Этот пользователь еще не прошел активацию и не может добавлять свои объекты"
77: End Sub
78:
79: 'активированный залогиненный юзер зашел на страничку к активированному юзеру
80: Sub RightToRightUser(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon, ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
81: UserMenu1.MenuUser = TargetUser
82: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.RightToRightUser
83: ThisTypePageLoad = TypeOfPageLoad.RightToRightUser
84: End Sub
85:
86: 'активированный залогиненный юзер зашел на страничку к неактивированному юзеру
87: Sub RightToLeftUser(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon, ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
88: UserMenu1.MenuUser = TargetUser
89: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.RightToLeftUser
90: ThisTypePageLoad = TypeOfPageLoad.RightToLeftUser
91: lErr1.Text = "Этот пользователь еще не прошел активацию и не может добавлять свои объекты"
92: End Sub
93:
94: 'неактивированный залогиненный юзер зашел на страничку к активированному
95: Sub LeftToRightUser(ByVal CurrentUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon, ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
96: UserMenu1.MenuUser = TargetUser
97: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.LeftToRightUser
98: ThisTypePageLoad = TypeOfPageLoad.LeftToRightUser
99: End Sub
100:
101: Sub CurrUserNotFound()
102: UserMenu1.Visible = False
103: 'AddLink1.Visible = False
104: lErr1.Text = "Ошибка. Пользователь не найден."
105: End Sub
106:
107: Sub CurrProfileNotFound()
108: UserMenu1.Visible = False
109: ' AddLink1.Visible = False
110: lErr1.Text = "Ошибка. Пользователь не найден."
111: End Sub
112:
113: 'аноним зашел к неактивированному юзеру
114: Sub AnonToLeftUser(ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Current As ProfileCommon)
115: ' AddLink1.Visible = False
116: ThisTypePageLoad = TypeOfPageLoad.AnonToLeftUser
117: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.AnonToLeftUser
118: lErr1.Text = "Этот пользователь еще не прошел активацию и не может добавлять свои объекты"
119: End Sub
120:
121: 'аноним зашел к активированному юзеру
122: Sub AnonToRightUser(ByVal TargetUser As MembershipUser, ByVal MyTypedProfile_Target As ProfileCommon)
123: ' AddLink1.Visible = False
124: ThisTypePageLoad = TypeOfPageLoad.AnonToRightUser
125: UserMenu1.ThisTypePageLoad = TypeOfPageLoad.AnonToRightUser
126: End Sub
127:
128: 'Нет юзера к которому заходим
129: Sub TargetUserNotFound()
130: UserMenu1.Visible = False
131: ' AddLink1.Visible = False
132: lErr1.Text = "Ошибка. Пользователь не найден."
133: End Sub
134:
135: 'нет профиля юзера, чья страничка вызвана
136: Sub TargetProfileNotFound()
137: UserMenu1.Visible = False
138: ' AddLink1.Visible = False
139: lErr1.Text = "Ошибка. Пользователь не найден."
140: End Sub
141:
142: #End Region
Как видите - так код получился гораздо нагляднее, чем если бы Page_Load была построена на 16-ти ветках Select Case. Этот код является превосходным дополнением моей странички Практическое применение наследования, полиморфизма, интерфейсов, дженериков и делегатов на примерах в Visual Basic .NET в части делегатов.
Теперь рассмотрим третий вариант вынесения общего кода в контрол. Я обычно пользуюсь таким вариантом для аутентификации. Возьмем для примера админку того же проекта вотпуск.
Вся левая часть с крупными линками - это отдельный контрол в который утоплен код проверки прав юзера на вход в админку.
1: <%@ Master Language="VB" CodeFile="M2.master.vb" Inherits="M2" %>
2: <%@ Register Src="AdminLink.ascx" TagName="AdminLink" TagPrefix="uc1" %>
3:
4: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5:
6: <html xmlns="http://www.w3.org/1999/xhtml" >
7: <head runat="server">
8: <title>CMS <asp:Literal runat="server" Text="<%$ appSettings:RealURL%>"/></title>
9: </head>
10: <body >
11: <form id="form1" runat="server">
12: <uc1:AdminLink ID="AdminLink1" runat="server" />
13: <div>
14: <asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
15: </asp:contentplaceholder>
16:
17: </div>
18: </form>
19: </body>
20: </html>
1: <%@ Control Language="VB" AutoEventWireup="false" CodeFile="AdminLink.ascx.vb" Inherits="AdminLink" %>
2: <table cellpadding="0" cellspacing="0">
3: ...
4: </table>
1: ''' <summary>
2: ''' Контрол защищает от левых входов
3: ''' </summary>
4: Partial Class AdminLink
5: Inherits System.Web.UI.UserControl
6:
7: Protected Sub AdminLink_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
8: '
9: HyperLink29.NavigateUrl = "http://foto." & System.Configuration.ConfigurationManager.AppSettings("RealURL")
10: HyperLink30.NavigateUrl = "http://video." & System.Configuration.ConfigurationManager.AppSettings("RealURL")
11: HyperLink31.NavigateUrl = "http://story." & System.Configuration.ConfigurationManager.AppSettings("RealURL")
12: HyperLink32.NavigateUrl = "http://poputi." & System.Configuration.ConfigurationManager.AppSettings("RealURL")
13: HyperLink37.NavigateUrl = "http://search." & System.Configuration.ConfigurationManager.AppSettings("RealURL")
14: HyperLink39.NavigateUrl = "http://" & System.Configuration.ConfigurationManager.AppSettings("RealURL")
15: '
16: If Not IsPostBack Then
17: If Not Me.Page.User.Identity.IsAuthenticated Then
18: Response.Redirect("Login.aspx")
19: Exit Sub
20: End If
21: If Not Roles.IsUserInRole(Me.Page.User.Identity.Name, "UserAdmin") Then
22: Response.Redirect(Votpusk.[GoTo].NotSupported & "?ErrorMessage=""Эта функция доступна только администраторам.""&URL=""" & Request.RawUrl & """")
23: End If
24: End If
25:
26: End Sub
27: End Class
Наконец четвертый вариант утапливанивая общего кода в код Master_Page. Это наиболее сложный вариант - когда не удается утопить общий код иначе. Ведь контролы (а Master-Page это тоже контрол) - выполняются от внутреннего вложенного к внешнему окаймляющему. Те код код master-page будет выполняться посдедним - и страничкb проекта будут готовитья, когда этот обший код в master-page еще не вызывался.
Но есть несколько вариантов, когда имеет смысл утапливать код в master page:
- Если все контролы проекта заведомо формируются в самый последний момент - в Page_Prerender. тогда возможно утапливать общий код проекта в page_load в master_page.
- Если нужно выполнить какие-то совершенно окончательные операции над страничкой (после того как сформировано основное содержимое всех контролов в page_load) - те в этом случае это будет общий код проекта, который выполняется самым последним перед отправкой странички клиенту. Пример - подписание странички ключом шифрования при использовании криптографии по клиентскому ключу в баузере. Или дописать какой-то общий яваскрипт, который сработает для логина (такой пример описан у меня на страничке Язва-скрипт в ASP.NET).
- Если на Master-page лежат контролы входа/аутентификации.
В качестве примера общего кода на мастер-педж проекта я приведу мой баг-трекер, который в принципе является одинм из моих комерческих продуктов - Bug_Tracker (инструмент разработки и эксплуатации программ) ( в упрощенном варианте является OpenSource Простейший баг-трекер). В виде продукта его только вот отсюда сгрузили сотни человек. А для моих собственных целей (для сопровождения багов в прогах, которые я выкладываю на http://freeware.vb-net.com/ и http://products.vb-net.com/ этот мой баг-трекер лежит вот тут - http://bug.vb-net.com/Default.aspx.
В этом проекте есть некий общий код, вынесенный на master-page. В данном случае этот общий код выполняет две функции:
- Залогинивание, которое можно выполнить, находясь на любой из форм этого сайта в режиме просмотра незалогиненнмы пользователем.
- Защиту этого сайта от копирования. Ибо это коммерческий продукт, активирующися после оплаты вот этим моим драйвером WebActivator - клиент/сервер защиты от копирования для платных программ (его упрощенная версия тоже является OpenSource - Remote SQL execute for PostgreSQL on GSM/GPRS channel with extreme compress and cryptography)
1: <%@ Master Language="VB" CodeFile="M1.master.vb" Inherits="M1" %>
2:
3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4:
5: <html xmlns="http://www.w3.org/1999/xhtml">
6: <head runat="server">
7: <title>Bug Tracker</title>
8: </head>
9: <body>
10: <form id="form1" runat="server">
11: <div style="text-align:left; display:inline;float:left">
12: <asp:ImageButton ID="ImageButton1" ImageUrl="~/BugImage/Top.gif" PostBackUrl="~/Default.aspx" runat="server" ValidationGroup="Always" />
13: </div>
14: <div style="text-align:right; display:inline;float:right">
15: <asp:Login ID="Login1" runat="server" LoginButtonText="Войти"
16: PasswordLabelText="Пароль" RememberMeText="Помнить" TitleText=""
17: UserNameLabelText="Email">
18: </asp:Login>
19: <asp:LinkButton ID="LinkButton1" runat="server" ValidationGroup="Always">Выйти</asp:LinkButton>
20: <asp:Label ID="LoginName1" runat="server" />
21: <asp:HyperLink ID="RegisterLink" runat="server" >Регистрация</asp:HyperLink><br />
22: <asp:HyperLink ID="RememberLink" runat="server" >Напомнить пароль</asp:HyperLink>
23: </div>
24: <div style="height:80px"></div>
25: <div>
26: <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
27:
28: </asp:ContentPlaceHolder>
29: </div>
30: </form>
31: </body>
32: </html>
1: Partial Class M1
2: Inherits System.Web.UI.MasterPage
3:
4: Protected Sub M1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
5:
6: 'защита/активация
7: If Not IsPostBack Then
8: Dim PointerToActivationCode As IntPtr
9: 'код активации, полученный от сервера
10: Dim RuntimeActivationCode As String
11: 'RuntimeActivationCode = Runtime.InteropServices.Marshal.PtrToStringBSTR(PointerToActivationCode)
12: Try
13: 'код проверки ключа активации
14: '....
15: '
16: Me.Page.ClientScript.RegisterOnSubmitStatement(Me.GetType, "DemoAlert", "alert('Demo version');")
17: Catch ex As Exception
18: Me.Page.ClientScript.RegisterOnSubmitStatement(Me.GetType, "DemoAlert", "alert('Demo version');")
19: End Try
20: Run:
21: End If
22: '
23: RegisterLink.NavigateUrl = System.Configuration.ConfigurationManager.AppSettings("UserRegisterURL")
24: RememberLink.NavigateUrl = System.Configuration.ConfigurationManager.AppSettings("UserRestorePassURL")
25: '
26: If HttpContext.Current.User.Identity.IsAuthenticated Then
27: Dim MyTypedProfile As ProfileCommon = Profile.GetProfile(HttpContext.Current.User.Identity.Name)
28: If MyTypedProfile IsNot Nothing Then
29: LoginName1.Text = MyTypedProfile.usNik
30: Else
31: LoginName1.Text = HttpContext.Current.User.Identity.Name
32: End If
33: LinkButton1.Visible = True
34: Login1.Visible = False
35: RegisterLink.Visible = False
36: RememberLink.Visible = False
37: Else
38: LoginName1.Visible = False
39: LinkButton1.Visible = False
40: Login1.Visible = True
41: RegisterLink.Visible = True
42: RememberLink.Visible = True
43: End If
44: End Sub
45:
46: Protected Sub Login1_LoggingIn(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.LoginCancelEventArgs) Handles Login1.LoggingIn
47: Dim MyTypedProfile As ProfileCommon = Profile.GetProfile(HttpContext.Current.User.Identity.Name)
48: If MyTypedProfile IsNot Nothing Then
49: LoginName1.Text = MyTypedProfile.usNik
50: Else
51: LoginName1.Text = HttpContext.Current.User.Identity.Name
52: End If
53: LinkButton1.Visible = True
54: Login1.Visible = False
55: RegisterLink.Visible = False
56: RememberLink.Visible = False
57: End Sub
58:
59: Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles LinkButton1.Click
60: FormsAuthentication.SignOut()
61: LoginName1.Visible = False
62: LinkButton1.Visible = False
63: Login1.Visible = True
64: RegisterLink.Visible = True
65: RememberLink.Visible = True
66: Response.Redirect(Request.RawUrl)
67: End Sub
68:
69: Protected Sub Login1_LoginError(ByVal sender As Object, ByVal e As System.EventArgs) Handles Login1.LoginError
70: LoginName1.Visible = False
71: LinkButton1.Visible = False
72: Login1.Visible = True
73: RegisterLink.Visible = True
74: RememberLink.Visible = True
75: End Sub
76: End Class
Обратите внимание, что если вы будете пользоваться таким же точно способом залогинивания - когда микрософтовские контролы для залогинивания сами находят стандартную базу ASP.NET юзеров и обрабатывают логины/пароли в этой базе, то вы должны точно в конфиге своего приложения сконфигурировать membership-провайдер:
1: ...
2: <connectionStrings>
3: <remove name="LocalSqlServer"/>
4: <add name="LocalSqlServer" connectionString="server=Dev;Initial Catalog=Bug;User ID=Bug;Password=123456" providerName="System.Data.SqlClient"/>
5: <add name="SQLServer_ConnectionStrings" connectionString="server=Dev;Initial Catalog=Bug;User ID=Bug;Password=123456" providerName="System.Data.SqlClient"/>
6: </connectionStrings>
7: ...
8: <appSettings>
9: ...
10: </appSettings>
11: <system.web>
12: <globalization culture="ru-RU"/>
13: <roleManager enabled="true" defaultProvider="AspNetSqlProvider">
14: <providers>
15: <remove name="AspNetSqlRoleProvider"/>
16: <remove name="AspNetWindowsTokenRoleProvider"/>
17: <add applicationName="/" name="AspNetSqlProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="LocalSqlServer"/>
18: </providers>
19: </roleManager>
20: <membership>
21: <providers>
22: <remove name="AspNetSqlMembershipProvider"/>
23: <add applicationName="/" name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider,System.Web, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="False" requiresUniqueEmail="True" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" passwordFormat="Hashed" maxInvalidPasswordAttempts="6" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>
24: </providers>
25: </membership>
26: <compilation debug="true">
27: <assemblies>
28: ...
29: </compilation>
30: <authentication mode="Forms"/>
31: <profile defaultProvider="SqlProvider">
32: <providers>
33: <clear/>
34: <add applicationName="/" name="SqlProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="LocalSqlServer"/>
35: </providers>
36: <properties>
37: ...
38: </properties>
39: </profile>
В заключение я покажу расширение первого варианта, когда строится некая иерархия классов, некоторые методы в которых обьвляются Overridable, а потом в вышестоящих классах переопределяются (с ключевым словом Overrides). Соотвественно - каждая форма проекта может наследовать тот или иной похожий класс.
1: Imports Microsoft.VisualBasic
2:
3: ''' <summary>
4: ''' Есть свойство для запоминания текущего рабочего XML - и оно всегда непустое
5: ''' </summary>
6: Public Class ProfileBasePage2
7: Inherits ProfileBasePage1
8:
9: Property WorkingXML As XElement
10: Get
11: Return Session("WorkingXML" & "_" & Request.QueryString("Type") & "_" & Request.QueryString("id"))
12: End Get
13: Set(ByVal value As XElement)
14: Session("WorkingXML" & "_" & Request.QueryString("Type") & "_" & Request.QueryString("id")) = value
15: End Set
16: End Property
17:
18: Private Sub ProfileBasePage_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
19: ReadCurrentUser()
20: ReadTargetProfile()
21: INI_NULL_Working_XML()
22: End Sub
23:
24: Overrides Sub INI_NULL_Working_XML()
25: Select Case Request.QueryString("Type")
26: Case "BankingCards"
27: If BankingCards_xml(0) Is Nothing Then
28: WorkingXML = New XElement("{http://Airts.vb-net.com/}" & "BankingCards")
29: Else
30: WorkingXML = BankingCards_xml(0)
31: End If
32: Case "InetMoney"
33: If InetMoney_xml(0) Is Nothing Then
34: WorkingXML = New XElement("{http://Airts.vb-net.com/}" & "InetMoney")
35: Else
36: WorkingXML = InetMoney_xml(0)
37: End If
38: Case "HardMoney"
39: If HardMoney_xml(0) Is Nothing Then
40: WorkingXML = New XElement("{http://Airts.vb-net.com/}" & "HardMoney")
41: Else
42: WorkingXML = HardMoney_xml(0)
43: End If
44: Case "Invoice"
45: If Invoice_xml(0) Is Nothing Then
46: WorkingXML = New XElement("{http://Airts.vb-net.com/}" & "Invoice")
47: Else
48: WorkingXML = Invoice_xml(0)
49: End If
50: Case "BankTransfer"
51: If BankTransfer_xml(0) Is Nothing Then
52: WorkingXML = New XElement("{http://Airts.vb-net.com/}" & "BankTransfer")
53: Else
54: WorkingXML = BankTransfer_xml(0)
55: End If
56: Case "Bonus"
57: If Bonus_xml(0) Is Nothing Then
58: WorkingXML = New XElement("{http://Airts.vb-net.com/}" & "Bonus")
59: Else
60: WorkingXML = Bonus_xml(0)
61: End If
62: Case "Reserved"
63: If Reserved_xml Is Nothing Then
64: WorkingXML = New XElement("{http://Airts.vb-net.com/}" & "Reserved")
65: Else
66: WorkingXML = Reserved_xml(0)
67: End If
68: Case "Common"
69: If Common_xml(0) Is Nothing Then
70: WorkingXML = New XElement("{http://Airts.vb-net.com/}" & "Common")
71: Else
72: WorkingXML = Common_xml(0)
73: End If
74: End Select
75: End Sub
76:
77: Sub SaveProfile()
78: Dim AirtsDB1 As New UserPaymentProfileDataContext()
79: Select Case Request.QueryString("Type")
80: Case "BankingCards"
81: Me.TargetUserPaymentProfile(0).BankingCardsProfile = WorkingXML
82: AirtsDB1.SaveBankingCardsUserProfile(New Guid(Me.TargetUser.id), WorkingXML)
83: DebugLog.TraceTXT(Me.AppRelativeVirtualPath, "BankingCardsSchema Save " & Me.TargetUser.id)
84: Case "InetMoney"
85: Me.TargetUserPaymentProfile(0).InetMoneyProfile = WorkingXML
86: AirtsDB1.SaveInetMoneyUserProfile(New Guid(Me.TargetUser.id), WorkingXML)
87: DebugLog.TraceTXT(Me.AppRelativeVirtualPath, "InetMoneySchema Save " & Me.TargetUser.id)
88: Case "HardMoney"
89: Me.TargetUserPaymentProfile(0).HardMoneyProfile = WorkingXML
90: AirtsDB1.SaveHardMoneyUserProfile(New Guid(Me.TargetUser.id), WorkingXML)
91: DebugLog.TraceTXT(Me.AppRelativeVirtualPath, "HardMoneySchema Save " & Me.TargetUser.id)
92: Case "Invoice"
93: Me.TargetUserPaymentProfile(0).InvoiceProfile = WorkingXML
94: AirtsDB1.SaveInvoiceUserProfile(New Guid(Me.TargetUser.id), WorkingXML)
95: DebugLog.TraceTXT(Me.AppRelativeVirtualPath, "InvoiceSchema Save " & Me.TargetUser.id)
96: Case "BankTransfer"
97: Me.TargetUserPaymentProfile(0).BankTransferProfile = WorkingXML
98: AirtsDB1.SaveBankTransferUserProfile(New Guid(Me.TargetUser.id), WorkingXML)
99: DebugLog.TraceTXT(Me.AppRelativeVirtualPath, "BankTransferSchema Save " & Me.TargetUser.id)
100: Case "Bonus"
101: Me.TargetUserPaymentProfile(0).BonusProfile = WorkingXML
102: AirtsDB1.SaveBonusUserProfile(New Guid(Me.TargetUser.id), WorkingXML)
103: DebugLog.TraceTXT(Me.AppRelativeVirtualPath, "BonusSchema Save " & Me.TargetUser.id)
104: Case "Reserved"
105: Me.TargetUserPaymentProfile(0).ReservedProfile = WorkingXML
106: AirtsDB1.SaveReservedUserProfile(New Guid(Me.TargetUser.id), WorkingXML)
107: DebugLog.TraceTXT(Me.AppRelativeVirtualPath, "ReservedSchema Save " & Me.TargetUser.id)
108: Case "Common"
109: Me.TargetUserPaymentProfile(0).CommonProfile = WorkingXML
110: AirtsDB1.SaveCommonUserProfile(New Guid(Me.TargetUser.id), Me.TargetUserPaymentProfile(0).ProfileName, Me.TargetUserPaymentProfile(0).CommonProfile)
111: DebugLog.TraceTXT(Me.AppRelativeVirtualPath, "InetMoneySchema Save " & Me.TargetUser.id)
112: End Select
113: End Sub
114:
115: End Class
116:
117: ''' <summary>
118: ''' Для работы с профилями
119: ''' админ видит любого юзера, чей id указан в параметрах
120: ''' информация в контролах доступна для изменению только админу, неадмин видит только свой профиль
121: ''' </summary>
122: Public Class ProfileBasePage1
123: Inherits ProfileBasePage
124:
125: Property TargetUser As CheckUser
126:
127: Property TargetUserPaymentProfile As System.Collections.Generic.List(Of GetOneUserPaymentProfileResult)
128: Property BankingCards_xml As Collections.Generic.IEnumerable(Of XElement)
129: Property InetMoney_xml As Collections.Generic.IEnumerable(Of XElement)
130: Property HardMoney_xml As Collections.Generic.IEnumerable(Of XElement)
131: Property Invoice_xml As Collections.Generic.IEnumerable(Of XElement)
132: Property BankTransfer_xml As Collections.Generic.IEnumerable(Of XElement)
133: Property Bonus_xml As Collections.Generic.IEnumerable(Of XElement)
134: Property Reserved_xml As Collections.Generic.IEnumerable(Of XElement)
135: Property Common_xml As Collections.Generic.IEnumerable(Of XElement)
136:
137: Private Sub ProfileBasePage_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
138: ReadCurrentUser()
139: ReadTargetProfile()
140: INI_NULL_Working_XML()
141: End Sub
142:
143: Overrides Sub ReadTargetProfile()
144: TargetUser = New CheckUser
145: 'информация в контролах доступна для изменению только админу, неадмин видит только свой профиль
146: If Not CurrentUser.IsAdmin Then
147: DisableControls(Me.Controls(0))
148: TargetUser = CurrentUser
149: Else
150: 'админ видит любого юзера, чей id указан в параметрах
151: If Request.QueryString("id") IsNot Nothing Then
152: If Request.QueryString("id") <> "" Then
153: TargetUser.GetUserByID(Request.QueryString("id"))
154: Else
155: TargetUser = CurrentUser
156: End If
157: Else
158: TargetUser = CurrentUser
159: End If
160: End If
161: '
162: ReadTargetUserPaymentProfile()
163: '
164: If Request.QueryString("Type") IsNot Nothing Then
165: Select Case Request.QueryString("Type")
166: Case "BankingCards"
167: BankingCards_xml = From AllColumn In Me.TargetUserPaymentProfile Select AllColumn.BankingCardsProfile
168: Case "InetMoney"
169: InetMoney_xml = From AllColumn In Me.TargetUserPaymentProfile Select AllColumn.InetMoneyProfile
170: Case "HardMoney"
171: HardMoney_xml = From AllColumn In Me.TargetUserPaymentProfile Select AllColumn.HardMoneyProfile
172: Case "Invoice"
173: Invoice_xml = From AllColumn In Me.TargetUserPaymentProfile Select AllColumn.InvoiceProfile
174: Case "BankTransfer"
175: BankTransfer_xml = From AllColumn In Me.TargetUserPaymentProfile Select AllColumn.BankTransferProfile
176: Case "Bonus"
177: Bonus_xml = From AllColumn In Me.TargetUserPaymentProfile Select AllColumn.BonusProfile
178: Case "Reserved"
179: Reserved_xml = From AllColumn In Me.TargetUserPaymentProfile Select AllColumn.ReservedProfile
180: Case "Common"
181: Common_xml = From AllColumn In Me.TargetUserPaymentProfile Select AllColumn.CommonProfile
182: End Select
183: End If
184: End Sub
185:
186: Sub ReadTargetUserPaymentProfile()
187: 'кеширование чтения профиля из базы с помощью LINQ
188: If Session("UserPaymentProfile_" & Me.TargetUser.id) Is Nothing Then
189: Dim AirtsDB As New UserPaymentProfileDataContext()
190: Dim AirtsDB_MemoryBuf As System.Collections.Generic.List(Of GetOneUserPaymentProfileResult) = AirtsDB.GetOneUserPaymentProfile(New Guid(Me.TargetUser.id)).ToList
191: Session("UserPaymentProfile_" & Me.TargetUser.id) = AirtsDB_MemoryBuf
192: End If
193: _TargetUserPaymentProfile = Session("UserPaymentProfile_" & Me.TargetUser.id)
194: End Sub
195:
196: Sub DisableControls(ByVal TopControl As System.Web.UI.Control)
197: Try
198: If TopControl.GetType.Name.Contains("TextBox") Then
199: Dim TextBox As Web.UI.WebControls.TextBox = CType(TopControl, Web.UI.WebControls.TextBox)
200: TextBox.Enabled = False
201: ElseIf TopControl.GetType.Name.Contains("CheckBox") Then
202: Dim CheckBox As Web.UI.WebControls.CheckBox = CType(TopControl, Web.UI.WebControls.CheckBox)
203: CheckBox.Enabled = False
204: ElseIf TopControl.GetType.Name.Contains("DropDownList") Then
205: Dim DropDownList As Web.UI.WebControls.DropDownList = CType(TopControl, Web.UI.WebControls.DropDownList)
206: DropDownList.Enabled = False
207: Else
208: If TopControl.Controls.Count > 0 Then
209: For Each OneControls As System.Web.UI.Control In TopControl.Controls
210: DisableControls(OneControls)
211: Next
212: End If
213: End If
214: Catch ex As Exception
215: Throw New Exception("Base page Error" & ex.Message)
216: End Try
217:
218: End Sub
219:
220: End Class
221:
222: ''' <summary>
223: ''' Только аутентификация и чтение профиля залогиненного юзера из базы
224: ''' </summary>
225: Public Class ProfileBasePage
226: Inherits System.Web.UI.Page
227:
228: Property CurrentUser As CheckUser
229:
230: Private Sub ProfileBasePage_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
231: ReadCurrentUser()
232: ReadTargetProfile()
233: INI_NULL_Working_XML()
234: End Sub
235:
236:
237: Sub ReadCurrentUser()
238: CurrentUser = New CheckUser
239: If HttpContext.Current.User.Identity.IsAuthenticated Then
240: 'прочитали профиль юзера из базы
241: CurrentUser.GetUserByMail(HttpContext.Current.User.Identity.Name)
242: Else
243: Response.Redirect("Login.aspx")
244: End If
245: End Sub
246:
247: Overridable Sub ReadTargetProfile()
248: 'в этом классе не делаем ничего
249: End Sub
250:
251: Overridable Sub INI_NULL_Working_XML()
252: 'в этом классе пусто
253: End Sub
254:
255: End Class
Итак, подведем итоги - на этой страничке я описал ЧЕТЫРЕ способа встраивания общего кода ASP-NET проекта в общую структуру проекта:
- В виде базовой странички, от которой наследуются все прочие странички.
- В виде отдельного класса (для удобства с делегатами-калбеками).
- В виде отдельного контрола.
- В виде кода master-page
Самый последний вариант - это многоярусная пирамида классов в базовой страничке проекта - расширение первого варианта размещения общего кода ASP.NET сайта.
|