DNN 研究路线图
首先我们从一个链接请求到达服务器开始讲起,来找出系统是如何处理各种要求的,从而整理出来我们需要的各个组件。
我们首先看看在 web.config 这个网站的配置文件当中,有下面一段配置。它意味着系统在处理连接请求时首先会通过下列过滤器插件的处理。
<add name="UrlRewrite" type="DotNetNuke.HttpModules.UrlRewriteModule, DotNetNuke.HttpModules.UrlRewrite" />
<add name="Exception" type="DotNetNuke.HttpModules.ExceptionModule, DotNetNuke.HttpModules.Exception" />
<!-- add name="Authentication" type="DotNetNuke.HttpModules.AuthenticationModule, DotNetNuke.HttpModules.Authentication" / -->
<add name="UsersOnline" type="DotNetNuke.HttpModules.UsersOnlineModule, DotNetNuke.HttpModules.UsersOnline" />
<add name="ProfilePrototype" type="Microsoft.ScalableHosting.Profile.ProfileModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562" />
<add name="AnonymousIdentificationPrototype" type="Microsoft.ScalableHosting.Security.AnonymousIdentificationModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562" />
<add name="RoleManagerPrototype" type="Microsoft.ScalableHosting.Security.RoleManagerModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562" />
<add name="DNNMembership" type="DotNetNuke.HttpModules.DNNMembershipModule, DotNetNuke.HttpModules.DNNMembership" />
<add name="Personalization" type="DotNetNuke.HttpModules.PersonalizationModule, DotNetNuke.HttpModules.Personalization" />
</httpModules>
首先处理连接请求的是 UrlRewriteModule 这个过滤器处理模块。这个模块的处理功能是将 DotNetNuke 的链接形式转化为正常?+ & 的模式(DNN的鼻祖IBuySpy)。但是在这个模块当中也封装了一些其他的处理。我们来看看HttpModule.UrlRewrite 的一些功能。这个项目当中主要的结构在后面章节描述。
HttpModule.UrlRewrite 当中主要入口模块或者主要控制程序是UrlRewriteModule.vb 当中的UrlRewriteModule 类。它继承了 IHttpModule。这个类需要实现 OnBeginRequest 这个 function , 用来处理提交到服务器的链接。
Dim requestedPath As String = app.Request.Url.AbsoluteUri
Dim Server As HttpServerUtility = app.Server
Dim Request As HttpRequest = app.Request
Dim Response As HttpResponse = app.Response
' URL validation
' check for ".." escape characters commonly used by hackers to traverse the folder tree on the server
' the application should always use the exact relative location of the resource it is requesting
'Dim strURL As String = Server.UrlDecode(Request.RawUrl)
Dim strURL As String = Request.Url.AbsolutePath
Dim strDoubleDecodeURL As String = Server.UrlDecode(Server.UrlDecode(Request.RawUrl))
If strURL.IndexOf("..") <> -1 Or strDoubleDecodeURL.IndexOf("..") <> -1 Then
Throw New HttpException(404, "Not Found")
End If
'fix for ASP.NET canonicalization issues http://support.microsoft.com/?kbid=887459
If (Request.Path.IndexOf(Chr(92)) >= 0 Or System.IO.Path.GetFullPath(Request.PhysicalPath) <> Request.PhysicalPath) Then
Throw New HttpException(404, "Not Found")
End If
'check if we are upgrading/installing
If Request.Url.LocalPath.ToLower.EndsWith("install.aspx") Then
Exit Sub
End If
' Remove querystring if exists.. it gets added on later
If (app.Request.Url.Query <> "") Then
requestedPath = requestedPath.Replace(app.Request.Url.Query, "")
End If
app.Context.Items.Add("UrlRewrite:OriginalUrl", app.Request.Url.AbsoluteUri)
Dim rules As Config.RewriterRuleCollection = Config.RewriterConfiguration.GetConfig().Rules
For i As Integer = 0 To rules.Count - 1
Dim lookFor As String = "^" & RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules(i).LookFor) & "$"
Dim re As Regex = New Regex(lookFor, RegexOptions.IgnoreCase)
If (re.IsMatch(requestedPath)) Then
Dim sendTo As String = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(requestedPath, rules(i).SendTo))
Dim sesMatch As Match = re.Match(requestedPath)
Dim sesUrlParams As String = sesMatch.Groups(2).Value
If (sesUrlParams.Trim().Length > 0) Then
sesUrlParams = sesUrlParams.Replace("\", "/")
Dim urlParams As String() = sesUrlParams.Split("/"c)
For x As Integer = 1 To urlParams.Length - 1
If (urlParams(x).Trim().Length > 0 And urlParams(x).ToLower <> glbDefaultPage.ToLower) Then
sendTo = sendTo & "&" & urlParams(x).Replace(".aspx", "").Trim() & "="
If (x < (urlParams.Length - 1)) Then
x += 1
If (urlParams(x).Trim <> "") Then
sendTo = sendTo & urlParams(x).Replace(".aspx", "")
End If
End If
End If
Next
End If
RewriterUtils.RewriteUrl(app.Context, sendTo)
Exit For
End If
Next
Dim TabId As Integer = -1
Dim PortalId As Integer = -1
Dim DomainName As String = Nothing
Dim PortalAlias As String = Nothing
Dim objPortalAliasInfo As PortalAliasInfo
' get TabId from querystring ( this is mandatory for maintaining portal context for child portals )
If Not (Request.QueryString("tabid") Is Nothing) Then
TabId = Int32.Parse(Request.QueryString("tabid"))
End If
' get PortalId from querystring ( this is used for host menu options as well as child portal navigation )
If Not (Request.QueryString("portalid") Is Nothing) Then
PortalId = Int32.Parse(Request.QueryString("portalid"))
End If
' alias parameter can be used to switch portals
If Not (Request.QueryString("alias") Is Nothing) Then
' check if the alias is valid
If Not PortalSettings.GetPortalAliasInfo(Request.QueryString("alias")) Is Nothing Then
' check if the domain name contains the alias
If InStr(1, Request.QueryString("alias"), DomainName, CompareMethod.Text) = 0 Then
' redirect to the url defined in the alias
Response.Redirect(GetPortalDomainName(Request.QueryString("alias"), Request), True)
Else ' the alias is the same as the current domain
PortalAlias = Request.QueryString("alias")
End If
End If
End If
' parse the Request URL into a Domain Name token
DomainName = GetDomainName(Request)
' PortalId identifies a portal when set
If PortalAlias Is Nothing Then
If PortalId <> -1 Then
PortalAlias = PortalSettings.GetPortalByID(PortalId, DomainName)
End If
End If
' TabId uniquely identifies a Portal
If PortalAlias Is Nothing Then
If TabId <> -1 Then
' get the alias from the tabid, but only if it is for a tab in that domain
PortalAlias = PortalSettings.GetPortalByTab(TabId, DomainName)
If PortalAlias Is Nothing Or PortalAlias = "" Then
'if the TabId is not for the correct domain
'see if the correct domain can be found and redirect it
objPortalAliasInfo = PortalSettings.GetPortalAliasInfo(DomainName)
If Not objPortalAliasInfo Is Nothing Then
If app.Request.Url.AbsoluteUri.ToLower.StartsWith("https://") Then
strURL = "https://" & objPortalAliasInfo.HTTPAlias.Replace("*.", "")
Else
strURL = "http://" & objPortalAliasInfo.HTTPAlias.Replace("*.", "")
End If
If strURL.ToLower.IndexOf(DomainName.ToLower()) = -1 Then
strURL += app.Request.Url.PathAndQuery
End If
Response.Redirect(strURL, True)
End If
End If
End If
End If
' else use the domain name
If PortalAlias Is Nothing Or PortalAlias = "" Then
PortalAlias = DomainName
End If
'using the DomainName above will find that alias that is the domainname portion of the Url
'ie. dotnetnuke.com will be found even if zzz.dotnetnuke.com was entered on the Url
objPortalAliasInfo = PortalSettings.GetPortalAliasInfo(PortalAlias)
If Not objPortalAliasInfo Is Nothing Then
PortalId = objPortalAliasInfo.PortalID
End If
' if the portalid is not known
If PortalId = -1 Then
If Not Request.Url.LocalPath.ToLower.EndsWith(glbDefaultPage.ToLower) Then
' allows requests for aspx pages in custom folder locations to be processed
Exit Sub
Else
'the domain name was not found so try using the host portal's first alias
If Convert.ToString(HostSettings("HostPortalId")) <> "" Then
PortalId = Convert.ToInt32(HostSettings("HostPortalId"))
' use the host portal
Dim objPortalAliasController As New PortalAliasController
Dim arrPortalAliases As ArrayList
arrPortalAliases = objPortalAliasController.GetPortalAliasArrayByPortalID(Integer.Parse(Convert.ToString(HostSettings("HostPortalId"))))
If arrPortalAliases.Count > 0 Then
'Get the first Alias
objPortalAliasInfo = CType(arrPortalAliases(0), PortalAliasInfo)
If app.Request.Url.AbsoluteUri.ToLower.StartsWith("https://") Then
strURL = "https://" & objPortalAliasInfo.HTTPAlias.Replace("*.", "")
Else
strURL = "http://" & objPortalAliasInfo.HTTPAlias.Replace("*.", "")
End If
If TabId <> -1 Then
strURL += app.Request.Url.Query()
End If
Response.Redirect(strURL, True)
End If
End If
End If
End If
If PortalId <> -1 Then
' load the PortalSettings into current context
Dim _portalSettings As PortalSettings = New PortalSettings(TabId, objPortalAliasInfo)
app.Context.Items.Add("PortalSettings", _portalSettings)
Else
' alias does not exist in database
' and all attempts to find another have failed
'this should only happen if the HostPortal does not have any aliases
Dim objStreamReader As StreamReader
objStreamReader = File.OpenText(Server.MapPath("~/404.htm"))
Dim strHTML As String = objStreamReader.ReadToEnd
objStreamReader.Close()
strHTML = Replace(strHTML, "[DOMAINNAME]", DomainName)
Response.Write(strHTML)
Response.End()
End If
这一节代码有些长,需要对它进行重构。这段代码实现的主要功能有:
1、 验证 URL 正确性。
a) 检查是否有“..”这种字符的存在,防止非法访问服务器目录。
b) 修改 Asp.net 中的一个漏洞。http://support.microsoft.com/?kbid=887459
c) 检查系统是是否在安装状态,这个部分我们省略掉。
2、 定义重写规则,这个部分我们在第二部分予以详细讲解。
3、 读取项目信息。这个部分原本不应该出现在重写模块。
a) 读取 TabID
b) 读取PortalId
c) 读取别称参数。别称用在在不同的 Portals 之间转换。
d) 解析域名。主要用在 Ip 地址与域名绑定上。通过这个功能实现了一个站点对应多个域名的功能。
e) 通过 tabid 取得 Portal 信息
f) 通过域名定义别称
g) 通过别称取得Portal信息
h) 通过 Portal id 获得protal信息
i) 通过上述操作,获得 Portalid 后取得 Portal 的设置信息,并且将设置信息保存在上下文当中。
关于 Portal 相关类结构我们在后面的章节进一步描述。
当 RewriterUtils 工具重写了 URL 之后,所有的请求将被传递给系统几个主要的入口页面。在 Portal 当中可以接受普通计算机发送过来的请求,但是也可以接受手机等其他特殊设备发送过来的请求。目前我们主要处理的是从普通计算机发送过来的请求。需要我们注意的有两点,第一、所有请求都有单一的页面入口处理。第二、Portal 程序都是以控件安装到我们的系统当中。
下面,我们来看看 Default.aspx 是如何处理页面链接请求的
2' DotNetNuke?- http://www.dotnetnuke.com
3' Copyright (c) 2002-2006
4' by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
5'
6' Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
7' documentation files (the "Software"), to deal in the Software without restriction, including without limitation
8' the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
9' to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10'
11' The above copyright notice and this permission notice shall be included in all copies or substantial portions
12' of the Software.
13'
14' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15' TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
17' CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18' DEALINGS IN THE SOFTWARE.
19'
20
21Imports System.IO
22Imports DotNetNuke.Entities.Tabs
23Imports DotNetNuke.UI.Skins
24
25Namespace DotNetNukeNamespace DotNetNuke.Framework
26 ''' -----------------------------------------------------------------------------
27 ''' Project : DotNetNuke
28 ''' Class : CDefault
29 '''
30 ''' -----------------------------------------------------------------------------
31 ''' <summary>
32 '''
33 ''' </summary>
34 ''' <remarks>
35 ''' </remarks>
36 ''' <history>
37 ''' [sun1] 1/19/2004 Created
38 ''' </history>
39 ''' -----------------------------------------------------------------------------
40 Public MustInherit Class CDefaultClass CDefault
41
42 Inherits DotNetNuke.Framework.PageBase
43
44 Public Comment As String = ""
45 Public Title As String = ""
46 Public Description As String = ""
47 Public KeyWords As String = ""
48 Public Copyright As String = ""
49 Public Generator As String = ""
50 Public Author As String = ""
51
52 Protected ScrollTop As System.Web.UI.HtmlControls.HtmlInputHidden
53 Protected SkinError As System.Web.UI.WebControls.Label
54 Protected SkinPlaceHolder As System.Web.UI.WebControls.PlaceHolder
55
56 Protected CSS As System.Web.UI.WebControls.PlaceHolder
57 Protected FAVICON As System.Web.UI.WebControls.PlaceHolder
58 Protected phDNNHead As System.Web.UI.WebControls.PlaceHolder
59
60Properties
85
86Private Methods
413
414Protected Methods
421
422Public Methods
444
445Event Handlers
576
577Web Form Designer Generated Code
585
586 End Class
587
588End Namespace
589
Default.aspx.vb 文件当中DefaultPage类继承了DotNetNuke.Framework.CDefault 。主要实现了三个页面事件,4 个 sub 和一个比较主要的 function , 调用顺序如下:
我们首先来讲一讲 Page_Init 这个事件。
1、 调用InitializePage 功能,主要处理下列事件:
a) 从上下文获取 PortalSettings
b) 根据 Tab name 重定向到特定的 tab
c) 如果是第一访问页面,那么重载数据避免被客户端缓存。
d) 设置 page title 和 stylesheet
e) 检查是否要显示 Assembly 版本
f) 设置背景图片
g) 设置 META tags, copyright, keywords and description
2、 装载皮肤控件
a) 如果 cookie 中有记载,就根据 cookie 设置装载控件。
b) 如果被分配了皮肤控件,就装载指定的控件
c) 为活动页面设置皮肤路径
3、 将皮肤装载到页面当中。
4、 调用客户端 API
在这个类当中另外响应事件是 Page_PreRender,主要调用了 ManageRequest 方法。
这个方法主要实现了联合管理和网站访问记录,可以暂时忽略。
在这段代码当中继续起主要作用的是 Skin 当中的控件装载。接下来我们分析一下Skin 类的装载功能。
我们先分析一下 Page_Init 事件处理过程:
' CODEGEN: This call is required by the ASP.NET Web Form Designer.
'
InitializeComponent()
Dim objModules As New ModuleController
Dim objModule As ModuleInfo = Nothing
Dim ctlPane As Control
Dim blnLayoutMode As Boolean = Common.Globals.IsLayoutMode
Dim bSuccess As Boolean = True
' iterate page controls
Dim ctlControl As Control
Dim objHtmlControl As HtmlControl
For Each ctlControl In Me.Controls
' load the skin panes,TopPanel,LeftPanel,ContentPanel,RightPanel,BottomPanel
If TypeOf ctlControl Is HtmlControl Then
objHtmlControl = CType(ctlControl, HtmlControl)
If Not objHtmlControl.ID Is Nothing Then
Select Case objHtmlControl.TagName.ToUpper
Case "TD", "DIV", "SPAN", "P"
' content pane
If ctlControl.ID <> "ControlPanel" Then
PortalSettings.ActiveTab.Panes.Add(ctlControl.ID)
End If
End Select
End If
End If
Next
'if querystring dnnprintmode=true, controlpanel will not be shown
If Request.QueryString("dnnprintmode") <> "true" Then
' ControlPanel processing,如果是管理员角色则显示控制面板
If (PortalSecurity.IsInRoles(PortalSettings.AdministratorRoleName.ToString) = True Or PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = True) Then
Dim objControlPanel As UserControl = Nothing
If Convert.ToString(PortalSettings.HostSettings("ControlPanel")) <> "" Then
' load custom control panel
objControlPanel = CType(LoadControl("~/" & Convert.ToString(PortalSettings.HostSettings("ControlPanel"))), UserControl)
End If
If objControlPanel Is Nothing Then
' load default control panel
objControlPanel = CType(LoadControl("~/" & glbDefaultControlPanel), UserControl)
End If
' inject ControlPanel control into skin
ctlPane = Me.FindControl("ControlPanel")
If ctlPane Is Nothing Then
Dim objForm As HtmlForm = CType(Me.Parent.FindControl("Form"), HtmlForm)
objForm.Controls.AddAt(0, objControlPanel)
Else
ctlPane.Controls.Add(objControlPanel)
End If
End If
End If
If Not IsAdminControl() Then ' master module
If PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AuthorizedRoles) Then
' check portal expiry date
Dim blnExpired As Boolean = False
If PortalSettings.ExpiryDate <> Null.NullDate Then
If Convert.ToDateTime(PortalSettings.ExpiryDate) < Now() And PortalSettings.ActiveTab.ParentId <> PortalSettings.AdminTabId And PortalSettings.ActiveTab.ParentId <> PortalSettings.SuperTabId Then
blnExpired = True
End If
End If
If Not blnExpired Then
If (PortalSettings.ActiveTab.StartDate < Now And PortalSettings.ActiveTab.EndDate > Now) Or blnLayoutMode = True Then
' process panes
If blnLayoutMode Then
Dim strPane As String
For Each strPane In PortalSettings.ActiveTab.Panes
ctlPane = Me.FindControl(strPane)
ctlPane.Visible = True
' display pane border
If TypeOf ctlPane Is HtmlContainerControl Then
CType(ctlPane, HtmlContainerControl).Style("border-top") = "1px #CCCCCC dotted"
CType(ctlPane, HtmlContainerControl).Style("border-bottom") = "1px #CCCCCC dotted"
CType(ctlPane, HtmlContainerControl).Style("border-right") = "1px #CCCCCC dotted"
CType(ctlPane, HtmlContainerControl).Style("border-left") = "1px #CCCCCC dotted"
End If
' display pane name
Dim ctlLabel As New Label
ctlLabel.Text = "<center>" & strPane & "</center><br>"
ctlLabel.CssClass = "SubHead"
ctlPane.Controls.AddAt(0, ctlLabel)
Next
End If
' dynamically populate the panes with modules
If PortalSettings.ActiveTab.Modules.Count > 0 Then
' loop through each entry in the configuration system for this tab
For Each objModule In PortalSettings.ActiveTab.Modules
' if user is allowed to view module and module is not deleted
If PortalSecurity.IsInRoles(objModule.AuthorizedViewRoles) = True And objModule.IsDeleted = False Then
' if current date is within module display schedule or user is admin
If (objModule.StartDate < Now And objModule.EndDate > Now) Or blnLayoutMode = True Then
' modules which are displayed on all tabs should not be displayed on the Admin or Super tabs
'如果模块不是在所有页面或超级页面显示
If objModule.AllTabs = False Or PortalSettings.ActiveTab.IsAdminTab = False Then
'查找模块的容器(TopPanel/LeftPanel/ContentPanel/..
Dim parent As Control = Me.FindControl(objModule.PaneName)
If parent Is Nothing Then
' the pane specified in the database does not exist for this skin
' insert the module into the default pane instead
parent = Me.FindControl(glbDefaultPane)
End If
If Not parent Is Nothing Then
' try to localize admin modules
If PortalSettings.ActiveTab.IsAdminTab Then
objModule.ModuleTitle = Services.Localization.Localization.LocalizeControlTitle(objModule.ModuleTitle, objModule.ControlSrc, "")
End If
'try to inject the module into the skin
'向模块内注入皮肤
Try
InjectModule(parent, objModule, PortalSettings)
Catch ex As Exception
bSuccess = False
End Try
Else ' no ContentPane in skin
Dim lex As ModuleLoadException
lex = New ModuleLoadException(PANE_LOAD_ERROR)
Controls.Add(New ErrorContainer(PortalSettings, MODULELOAD_ERROR, lex).Container)
LogException(lex)
Err.Clear()
End If
End If
End If
End If
Next objModule
End If
Else
Skin.AddPageMessage(Me, "", TABACCESS_ERROR, UI.Skins.Controls.ModuleMessage.ModuleMessageType.YellowWarning)
End If
Else
Skin.AddPageMessage(Me, "", String.Format(CONTRACTEXPIRED_ERROR, PortalSettings.PortalName, GetMediumDate(PortalSettings.ExpiryDate.ToString), PortalSettings.Email), UI.Skins.Controls.ModuleMessage.ModuleMessageType.RedError)
End If
Else
Response.Redirect(AccessDeniedURL(TABACCESS_ERROR), True)
End If
Else ' slave module
Dim ModuleId As Integer = -1
Dim Key As String = ""
' get ModuleId
If Not IsNothing(Request.QueryString("mid")) Then
ModuleId = Int32.Parse(Request.QueryString("mid"))
End If
' get ControlKey
If Not IsNothing(Request.QueryString("ctl")) Then
Key = Request.QueryString("ctl")
End If
' initialize moduleid for modulesettings
If Not IsNothing(Request.QueryString("moduleid")) And (Key.ToLower = "module" Or Key.ToLower = "help") Then
ModuleId = Int32.Parse(Request.QueryString("moduleid"))
End If
If ModuleId <> -1 Then
' get master module security settings
objModule = objModules.GetModule(ModuleId, PortalSettings.ActiveTab.TabID)
If Not objModule Is Nothing Then
If objModule.InheritViewPermissions Then
objModule.AuthorizedViewRoles = PortalSettings.ActiveTab.AuthorizedRoles
End If
End If
End If
If objModule Is Nothing Then
' initialize object not related to a module
objModule = New ModuleInfo
objModule.ModuleID = ModuleId
objModule.ModuleDefID = -1
objModule.TabID = PortalSettings.ActiveTab.TabID
objModule.AuthorizedEditRoles = ""
objModule.AuthorizedViewRoles = ""
End If
' initialize moduledefid for modulesettings
If Not IsNothing(Request.QueryString("moduleid")) And (Key.ToLower = "module" Or Key.ToLower = "help") Then
objModule.ModuleDefID = -1
End If
' override slave module settings
If Request.QueryString("dnnprintmode") <> "true" Then
objModule.ModuleTitle = ""
End If
objModule.Header = ""
objModule.Footer = ""
objModule.StartDate = DateTime.MinValue
objModule.EndDate = DateTime.MaxValue
objModule.PaneName = glbDefaultPane
objModule.Visibility = VisibilityState.None
objModule.Color = ""
If Request.QueryString("dnnprintmode") <> "true" Then
objModule.Alignment = "center"
End If
objModule.Border = ""
objModule.DisplayTitle = True
objModule.DisplayPrint = False
objModule.DisplaySyndicate = False
' get portal container for slave module
Dim objSkin As SkinInfo = SkinController.GetSkin(SkinInfo.RootContainer, PortalSettings.PortalId, SkinType.Portal)
If Not objSkin Is Nothing Then
objModule.ContainerSrc = objSkin.SkinSrc
Else
objModule.ContainerSrc = "[G]" & SkinInfo.RootContainer & glbDefaultContainerFolder & glbDefaultContainer
End If
objModule.ContainerSrc = SkinController.FormatSkinSrc(objModule.ContainerSrc, PortalSettings)
objModule.ContainerPath = SkinController.FormatSkinPath(objModule.ContainerSrc)
' get the pane
Dim parent As Control = Me.FindControl(objModule.PaneName)
' load the controls
Dim objModuleControls As New ModuleControlController
Dim objModuleControl As ModuleControlInfo
Dim intCounter As Integer
Dim arrModuleControls As ArrayList = objModuleControls.GetModuleControlsByKey(Key, objModule.ModuleDefID)
For intCounter = 0 To arrModuleControls.Count - 1
objModuleControl = CType(arrModuleControls(intCounter), ModuleControlInfo)
' initialize control values
objModule.ModuleControlId = objModuleControl.ModuleControlID
objModule.ControlSrc = objModuleControl.ControlSrc
objModule.ControlType = objModuleControl.ControlType
objModule.IconFile = objModuleControl.IconFile
objModule.HelpUrl = objModuleControl.HelpURL
If Not Null.IsNull(objModuleControl.ControlTitle) Then
' try to localize control title
objModule.ModuleTitle = Localization.LocalizeControlTitle(objModuleControl.ControlTitle, objModule.ControlSrc, Key)
End If
' verify that the current user has access to this control
Dim blnAuthorized As Boolean = True
Select Case objModule.ControlType
Case SecurityAccessLevel.Anonymous ' anonymous
Case SecurityAccessLevel.View ' view
If PortalSecurity.IsInRole(PortalSettings.AdministratorRoleName) = False And PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = False Then
If Not PortalSecurity.IsInRoles(objModule.AuthorizedViewRoles) Then
blnAuthorized = False
End If
End If
Case SecurityAccessLevel.Edit ' edit
If PortalSecurity.IsInRole(PortalSettings.AdministratorRoleName) = False And PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = False Then
If Not PortalSecurity.IsInRoles(objModule.AuthorizedViewRoles) Then
blnAuthorized = False
Else
If Not PortalSecurity.HasEditPermissions(objModule.ModulePermissions) Then
blnAuthorized = False
End If
End If
End If
Case SecurityAccessLevel.Admin ' admin
If PortalSecurity.IsInRole(PortalSettings.AdministratorRoleName) = False And PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = False Then
blnAuthorized = False
End If
Case SecurityAccessLevel.Host ' host
Dim objUserInfo As UserInfo = UserController.GetCurrentUserInfo
If Not objUserInfo.IsSuperUser Then
blnAuthorized = False
End If
End Select
If blnAuthorized Then
'try to inject the module into the skin
Try
InjectModule(parent, objModule, PortalSettings)
Catch ex As Exception
bSuccess = False
End Try
Else
Response.Redirect(AccessDeniedURL(MODULEACCESS_ERROR), True)
End If
Next
End If
If Not blnLayoutMode Then
CollapseUnusedPanes()
End If
If Not Request.QueryString("error") Is Nothing Then
Skin.AddPageMessage(Me, CRITICAL_ERROR, Server.HtmlEncode(Request.QueryString("error")), UI.Skins.Controls.ModuleMessage.ModuleMessageType.RedError)
End If
If Not (PortalSecurity.IsInRoles(PortalSettings.AdministratorRoleName) = True Or PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = True) Then
' only display the warning to non-administrators (adminsitrators will see the errors)
If Not bSuccess Then
Skin.AddPageMessage(Me, MODULELOAD_WARNING, String.Format(MODULELOAD_WARNINGTEXT, PortalSettings.Email), UI.Skins.Controls.ModuleMessage.ModuleMessageType.YellowWarning)
End If
End If
1、InitializeComponent
2、迭代处理 Skin 界面当中所有的控件。因为在 Skin 界面当中会定义一些画板(画板-Pane,它分为5种画板类型TopPane,LeftPane,ContentPane,RightPane,BottomPane),并且将画板的 ID 记录在 PortalSettings.ActiveTab.Panes 中
3、判断是否是打印模式。如果是正常模式且有管理员权限需要显示 ControlPanel ,我们暂时不考虑这个部分
4、判断是否为主要处理模式
对于每个当前页面指定的模块找到相应的 Pane ,并且在装载 Title 时考虑全球化的问题
如果装载出错,处理页面异常。
5、判断是否为次要处理模式,主要为管理模块设置。
6、判断 blnLayoutMode 模式
在整个系统当中比较核心的一个方法是 InjectModule
这个函数在处理过程当中分为下面几个步骤:
1、装载容器
2、装载模块
Portal 信息类结构设计
Tab 类簇结构设计
HttpModule.UrlRewrite
Module 类簇设计
Module 类簇设计是整个系统当中比较复杂的一个部分。它是 DotNetNuke 框架得以迅速扩展的基础。 Module 类簇主要包括下面几个部分:
1、 DesktopModule
2、 ModuleAction
3、 ModuleControl
4、 Module & ModuleSetting