LitwareBranding 解决方案介绍
为品牌管理创建实用类
换出母版页
在 Web.config 文件中注册 HttpModule
在功能激活期间化标记
自从我开始使用 SharePo® 技术起就经常会听到个请求公司总是希望创建独特站点而不是使用标准 SharePo 站点无论您使用 SharePo 技术创建面向 Internet 公司网站WebSite还是创建拥有众多团队(Team)协作站点 Intranet 环境都可能会需要管理 SharePo 站点可视元素例如页面布局以及字体和颜色使用等
Windows® SharePo Services (WSS) 3.0 通过主题提供标记用户可以通过将 WSS 主题应用到站点来更改其外观请注意WSS 中主题和 ASP.NET 中完全区别WSS 通过将级联样式表 (CSS) 文件从 Web 服务器文件系统复制到当前站点上下文并动态从各个页面链接到此 CSS 文件来为主题实现其基础结构
WSS 主题有些限制使得开发人员对其兴趣大减第个限制是 WSS 主题无法通过集成自定义母版页来自定义站点内使用页面布局而且WSS 主题只能基于每个站点应用而不能跨站点集合应用不支持次性将主题应用到站点集合中所有站点必须分别转到各个站点并应用同主题以保持整个站点集合在外观和功能上致性
SharePo Designer 为在 WSS 或 Microsoft® Office SharePo Server (MOSS) 2007 中标记站点提供了另种思路方法您可以使用 SharePo Designer 自定义站点母版页并编辑和集成自定义 CSS 文件但是处理基于标准 WSS 站点站点集合时SharePo Designer 未能提供种思路方法来同步站点集合所有站点以使用同版本自定义母版页这可能会导致不得不跨多个母版页文件来复制和粘贴您母版页剪辑
如果将 SharePo Designer 和 MOSS 配合使用情况会好些 MOSS 通过使用发布门户提供了 Web 内容管理 (WCM) 基础结构MOSS 发布门户是个站点集合其中包含发布站点可以自动同步所有站点页面以使用相同母版页和相同 CSS 文件
但务必要记住使用 SharePo Designer 创建适用于跨多个站点集合或用于企业方案标记解决方案时有些需要注意限制请记住使用 SharePo Designer 所做更改在特定站点上下文中始终被作为次性自定义内容这意味着使用 SharePo Designer 进行自定义可能需要些窍门技巧或可能无法在站点集合的间或场的间进行迁移此外将使用 SharePo Designer 进行站点自定义集成到源代码管理系统(如 Visual Studio® Team )中是件不切合实际事情
本月我将介绍如何为 SharePo 站点开发自定义标记解决方案此解决方案将利用 WSS 功能在站点集合级别集成自定义母版页和自定义 CSS 文件我将会对个名为 LitwareBranding 举例标记解决方案中代码加以介绍说明此解决方案是使用 Visual Studio 项目进行开发并使用解决方案包进行部署您可以在本期代码下载中找到全部代码
采用 Visual Studio 和生成解决方案包这两个原因使得将标记解决方案部署到运行 WSS 3.0 或 MOSS 2007 任何场中均成为可能这也使得为每个母版页和 CSS 文件(此文件可以在多个站点集合或场中重复使用)创建单个源文件变得更加容易此外和使用 SharePo Designer 相比Visual Studio 思路方法可能更具吸引力它允许将所有源文件签入到源代码管理系统中您还可以更轻松地将工作从开发场转移到过渡场进行测试然后投入生产
LitwareBranding 解决方案介绍
本月专栏附带了个名为 LitwareBranding 举例 Visual Studio 项目图 1 显示了 Visual Studio 中 LitwareBranding 项目结构正如您所看到该解决方案使用了 3种区别功能设计而成在本月专栏中我将利用整个篇幅对其用途和实现加以介绍说明此解决方案中核心功能被命名为 LitwareBranding它被设计为由 WSS 或 MOSS 站点集合范围内用户激活LitwareBranding 功能激活将强制 LitwareBranding 解决方案应用本月专栏中将要介绍所有标记技术
图 1 Visual Studio 中 LitwareBranding 解决方案
下面我们开始代码演练首先查看被命名为 LitwareBranding 核心功能所对应 feature.xml 文件如图 2 所示LitwareBranding 功能是使用 Site Scope 属性值定义这意味着它已被限制在站点集合级别这种构思出发点是站点集合所有者应该能够激活单个功能以将 Litware 公司标记应用到当前站点集合内所有站点
图 2 Feature.xml
<Feature
Id="065E2243-B968-4F14-BAAE-610BB975EFB7"
Title="A sample feature: LitwareBranding"
Description="Demoware created for Ted Pattison's OfficeSpace column"
Hidden="FALSE"
Scope="Site"
ImageUrl="LitwareBrandingAfricanPith32.g"
ReceiverAssembly="LitwareBranding, [4-part assembly name]"
ReceiverClass="LitwareBranding.FeatureReceiver"
xmlns="http://schemas.microsoft.com/sharepo/">
<ElementManests>
<ElementManest Location="elements.xml"/>
<ElementManest Location="stapling.xml" />
<ElementFile Location="LitwareBranding.master"/>
</ElementManests>
</Feature>
LitwareBranding 功能包含个名为 LitwareBranding.master 母版页模板和个名为 elements.xml 元素清单elements.xml 清单内包含声明性 XML 置备逻辑可用于创建此母版页模板例子这逻辑由带有内部 File 元素 Module 元素定义:复制代码
<Module Name="MasterPages"
Path="" List="116"
Url="_catalogs/masterpage" >
<File Url="LitwareBranding.master"
Type="GhostableInLibrary" />
</Module>
在功能激活期间此 Module 元素会强制 WSS 在顶级站点母版页库中置备个名为 LitwareBranding.master 母版页模板例子此母版页例子置备完毕后便可以提供针对 WSS 对象模型编程代码以同步站点集合内链接到此母版页页面对此我将在下部分加以介绍为品牌管理创建实用类
LitwareBranding 项目包含个名为 BrandManager 类此实用类封装了针对 WSS 对象模型编程所有代码可应用和删除各种标记元素BrandManager 类提供了些静态思路方法可完成以下任务:
同步链接到 LitwareBranding.master 站点页面
同步使用备选 CSS 文件页面
同步使用自定义图形作为站点徽标页面
添加对换出应用页面母版页支持
在深入了解具体成员的前请先看下图 3其中显示了 BrandManager 类所有成员该类包含多个静态属性用于解析指向各种资源(如母版页和 CSS 文件) URL例如SiteCollectionUrl 属性可返回 Web 应用相对于当前站点集合路径DefaultMasterPageUrl 可返回 Web 应用相对于名为 default.master 默认母版页路径此默认母版位于当前站点集合顶级站点母版页库中此路径可使用 SiteCollectionUrl 属性以及下列站点相对路径进行解析:
复制代码
_catalogs/masterpage/default.master
图 3 BrandManager 类 复制代码
public BrandManager {
// read-only properties
public SiteCollectionUrl
public DefaultMasterPageUrl
public CustomMasterPageUrl
public CustomCssUrl
public CustomSiteLogoUrl
// utility branding methods
public void ConfigureMasterUrl(bool ApplyMasterUrl) {}
public void ConfigureCustomMasterUrl(bool ApplyCustomMasterUrl) {}
public void ConfigureAlternateCss(bool ApplyCustomCss) {}
public void ConfigureSiteLogo(bool ApplySiteLogo) {}
public void ConfigureApplicationPageMaster(bool ApplyApplicationPageMaster) {}
}
CustomMasterPageUrl 属性可返回 Web 应用相对于名为 LitwareBranding.master 母版页例子路径此例子位于当前站点集合顶级站点母版页库中此路径可使用 SiteCollectionUrl 属性以及下列站点相对路径进行解析:复制代码
_catalogs/masterpage/litwarebranding.master
现在让我们研究下 ConfigureMasterUrl 思路方法它会枚举当前站点集合内每个站点并会更新各站点 MasterUrl 属性以指向自定义母版页或默认母版页:复制代码
public void ConfigureMasterUrl(bool ApplyMasterUrl) {
// determine MasterUrl property ting
MasterUrlPath =
(ApplyMasterUrl ?
CustomMasterPageUrl :
DefaultMasterPageUrl);
// update MasterUrl property for all sites
foreach (SPWeb site in SPContext.Current.Site.AllWebs) {
site.MasterUrl = MasterUrlPath;
site.Update;
}
}
请注意MasterUrl 属性会影响使用 ~masterurldefault.master MasterPageFile 属性设置所创建所有站点页面其中包括标准 default.aspx 页面模板它为许多 SharePo 站点模板(包括工作组网站WebSite和空白网站WebSite)提供主页还包含标准 WSS 列表类型所使用窗体页面(如 AllItems.aspx 和 NewItem.aspx)当您更新 MasterUrl 属性时MOSS 发布站点中页面布局不会受到影响这包括 MOSS 发布站点页面库中所有内容页面
相反这些内容页面会对 MastePageFile 属性使用 ~masterurlcustom.master 形式动态令牌此令牌区别于 ~masterurlcustom.master 令牌它是使用 CustomMasterUrl 属性而非 MasterUrl 属性切换出因此BrandManager 类提供了另个名为 ConfigureCustomMasterUrl 思路方法可用于切换出在 MOSS 发布站点页面库中创建内容页面母版页
public void ConfigureCustomMasterUrl(
bool ApplyCustomMasterUrl) {
// determine MasterUrl property ting
CustomMasterUrlPath =
(ApplyCustomMasterUrl ?
CustomMasterPageUrl :
DefaultMasterPageUrl);
// update MasterUrl property for all sites
foreach (SPWeb site in SPContext.Current.Site.AllWebs) {
site.CustomMasterUrl = CustomMasterUrlPath;
site.Update;
}
}
除了换出母版页的外LitwareBranding 解决方案还集成了个名为 styles.css 自定义 CSS 文件LitwareBranding 解决方案采用策略是将名为 styles.css CSS 文件部署到 LAYOUTS 目录内部所嵌套目录中以便能够将其次性部署到每个前端 Web 服务器文件系统中在 LAYOUTS 目录内进行部署优点在于 style.css 的类文件可以次性部署到 Web 服务器文件系统中而且仍可使用 CustomCssUrl 属性所返回标准 URL 从当前场内任何站点进行访问:public CustomCssUrl {
get {
"/_layouts/1033/STYLES/LitwareBranding/styles.css";
}
}
BrandManager 类提供了个名为 ConfigureAlternateCss 思路方法它使用 CustomCssUrl 属性将 URL 分配给当前站点集合内各站点 AlternateCSS 属性:public void ConfigureAlternateCss(bool ApplyCustomCss) {
// determine MasterUrl property ting
AlternateCssUrl =
(ApplyCustomCss ?
CustomCssUrl :
.Empty);
// update AlternateCssUrl for all sites
foreach (SPWeb site in SPContext.Current.Site.AllWebs) {
// make sure no theme is enabled
site.ApplyTheme(.Empty);
// apply custom CSS file
site.AlternateCssUrl = AlternateCssUrl;
site.Update;
}
}
WSS 中内置标记功能还提供了种更换显示在页面左上角标准 WSS 站点徽标简单思路方法LitwareBranding 解决方案通过包括名为 SiteLogo.g 自定义图形文件(被部署在 IMAGES 目录内嵌套目录中)来运用此功能和名为 styles.css CSS 文件样图形文件 SiteLogo.g 也是通过这种方式部署并且可以使用 CustomSiteLogoUrl 属性所返回 URL 从当前场内任何站点进行访问:public CustomSiteLogoUrl {
get {
"/_layouts/images/LitwareBranding/SiteLogo.g";
}
}
BrandManager 类 ConfigureSiteLogo 思路方法被编写为枚举当前站点集合所有站点并更新 SiteLogoUrl 属性:public void ConfigureSiteLogo(bool ApplySiteLogo) {
// determine SiteLogoUrl property ting
SiteLogoUrl =
(ApplySiteLogo ?
CustomSiteLogoUrl :
.Empty);
// update AlternateCssUrl for all sites
foreach (SPWeb site in SPContext.Current.Site.AllWebs) {
site.SiteLogoUrl = SiteLogoUrl;
site.Update;
}
}
换出母版页
虽然 SharePo 可使换出站点页面母版页相对容易些但它并没有为换出在 LAYOUTS 目录外运行内嵌式应用页面(如标准 WSS 站点设置页面 tings.aspx)母版页提供种直观方式这些应用页面均被链接到 WSS 在 LAYOUTS 目录内部署名为 application.master 标准 WSS 母版页但是如果要创建是可以换出站点集合内所有站点页面母版页标记解决方案则您可能希望通过换出应用页面(如 tings.aspx)母版页来使其可以使用自定义母版页从而创建致外观
LitwareBranding 解决方案演示了如何换出链接到标准母版页文件 application.master 所有应用页面母版页在用于换出母版页技术中包括了如何实现自定义 HttpModule它将在名为 PreInit ASP.NET 页面生命周期中为其中个事件注册个事件处理此事件是当您希望在化页面请求处理过程中换出母版页时ASP.NET 编程模型要求您执行事件
类 LitwareBrandingHttpModule 将提供在 LitwareBranding 解决方案中用来换出母版页 HttpModule(请参见图 4)此 HttpModule 类会为 Init 思路方法中 PreRequestHandlerExecute 事件注册个处理在 PreRequestHandlerExecute 事件处理思路方法实现过程中HttpModule 类可决定请求是否基于从 ASP.NET Page 类派生而来 HttpHandler 对象只有当请求基于 Page 派生对象时HttpModule 类才会从 PreInit 事件注册事件处理PreRequestHandlerExecute 事件处理中代码还会执行检查以确保传入请求以 _layouts 目录内页面作为目标在处理 WSS 中应用页面时始终都遵循此原则
图 4 交换母版页和应用页面
using ;
using .Web;
using .Web.UI;
using Microsoft.SharePo;
LitwareBranding {
public LitwareBrandingHttpModule : IHttpModule {
public void Init(HttpApplication context) {
context.PreRequestHandlerExecute
EventHandler(context_PreRequestHandlerExecute);
}
void context_PreRequestHandlerExecute(object sender, EventArgs e) {
Page page = HttpContext.Current.CurrentHandler as Page;
(page != null) {
// register handler for PreInit event
page.PreInit EventHandler(page_PreInit);
}
}
void page_PreInit(object sender, EventArgs e) {
// IF – requested page links to application.master
// THEN – dynamically mody page to link to custom .master file
}
public void Dispose { /* empty implementation */ }
}
}
请切记HttpModule 不能部署在单个站点集合 WSS 场中相反必须按照全有或全无主张在 Web 应用级别配置 HttpModule但是Web 应用可能包含成百上千个站点集合可能只有某些站点集合已启用了 LitwareBranding 功能因此HttpModule 类 PreInit 事件处理必须能够确定当前站点集合是否配置了为其应用页面换出母版页行为通过在站点集合顶级站点中创建自定义属性来指明是否应启用换出应用页面母版页这功能LitwareBranding 解决方案成功解决了此问题查看在 BrandManager 类中定义 ConfigureApplicationPageMaster 思路方法实现过程:
public void ConfigureApplicationPageMaster(
bool ApplyApplicationPageMaster) {
SPWeb TopLevelSite = SPContext.Current.Site.RootWeb;
(ApplyApplicationPageMaster) {
TopLevelSite.Properties["UseCustomApplicationPageMaster"] = "True";
}
{
TopLevelSite.Properties["UseCustomApplicationPageMaster"] = "False";
}
TopLevelSite.Properties.Update;
}
此思路方法在顶级站点中创建了个名为 UseCustomApplicationPageMaster 自定义属性并为其分配了值 True现在HttpModule 中 PreInit 事件处理思路方法实现可以在当前站点集合内查找此属性以了解它是否已被配置为允许换出应用页面母版页请注意PreInit 事件处理还会执行多项其他检查以确定在当前请求上下文中是否适合换出母版页(请参见图 5)图 5 PreInit 事件处理
void page_PreInit(object sender, EventArgs e) {
Page page = sender as Page;
((page != null) &&
(page.MasterPageFile != null) &&
(page.Request.Url.AbsolutePath.Contains("_layouts")) &&
(SPContext.Current != null) ) {
// inspect UseCustomApplicationPageMaster property
SPWeb site = SPContext.Current.Site.RootWeb;
UseCustomApplicationPageMaster =
site.Properties["UseCustomApplicationPageMaster"];
((!.IsNullOrEmpty(UseCustomApplicationPageMaster)) &&
(UseCustomApplicationPageMaster.Equals("True"))) {
// now replace application.master with customized version
(page.MasterPageFile.Contains("application.master")) {
page.MasterPageFile = "/_layouts/LitwareBranding/application.master";
}
}
}
}
当 PreInit 事件处理确定当前站点集合已被配置为允许换出应用页面母版页并且当前页面已链接到 application.master 后它会修改当前 ASP.NET Page 对象 MasterPageFile 属性以使用 LAYOUTS 目录下特定解决方案目录中自定义母版页目录路径如下:/_layouts/LitwareBranding/application.master
在 Web.config 文件中注册 HttpModule
使用 WSS 和 MOSS 部署业务解决方案时最好在解决方案包中分配您开发工作例如Visual Studio 项目 LitwareBranding 构建了个名为 LitwareBranding.wsp 单解决方案包利用它可以简单可靠地将此解决方案部署到运行 WSS 3.0 或 MOSS 2007 任何场中但是LitwareBranding 解决方案需要将 HttpModule 条目添加到各 Web 应用 web.config 文件中而此应用将运行在激活了 LitwareBranding 功能站点集合中
为更新特定 Web 应用内 web.config 文件LitwareBranding 解决方案使用了名为 LitwareBrandingWebApplication 第 2个功能此功能仅在 Web 应用级别有效并且还配置了个功能接收器类当此功能在特定 Web 应用范围内激活和停用时会触发事件处理:
<Feature
Id="FF739C76-0B08-4bc2-A3A2-F61524B492D8"
Title="Litware Branding Support Feature (WebApplication)"
Scope="WebApplication"
Hidden="False"
ReceiverClass="LitwareBranding. FeatureReceiverWebApplication"
ReceiverAssembly="LitwareBranding, [4-part assembly name]"
xmlns="http://schemas.microsoft.com/sharepo/">
<!-- no declarative elements -->
<ElementManests />
</Feature>
和任何其他功能接收器类样FeatureReceiverWebApplication 类继承自 SPFeatureReceiver 类并取代了名为 FeatureInstalled、FeatureActivated、FeatureDecactivating 和 FeatureUning 4个处理思路方法FeatureActivated 实现将 HttpModule 条目添加到当前 Web 应用 web.config 文件中FeatureDeactivating 实现可通过删除 HttpModule 条目来反转该操作如果您需要将某个条目添加到 web.config 文件中最好使用 WSS 对象模型中 SPWebConfigModication 类FeatureReceiverWebApplication 类包含个名为 CreateHttpModuleModication 实用思路方法用于创建和化 SPWebConfigModication 例子然后将其以返回值形式传回(请参见图 6)
图 6 CreateHttpModuleModication
public SPWebConfigModication CreateHttpModuleModication {
SPWebConfigModication modication;
ModName = "add[@name='LitwareBrandingModule']";
ModXPath = "configuration/system.web/httpModules";
modication = SPWebConfigModication(ModName, ModXPath);
modication.Owner = "LitwareBranding";
modication.Sequence = 0;
modication.Type =
SPWebConfigModication.SPWebConfigModicationType.EnsureChildNode;
modication.Value =
@"<add name=""LitwareBrandingModule"" " + @ "type="
"LitwareBranding.LitwareBrandingHttpModule, [4-part assembly name]"
" />";
modication;
}
当您有了可以返回化 SPWebConfigModication 对象实用思路方法(如 CreateHttpModuleModication)后即可简单地从事件处理(如 FeatureActivated 和 FeatureDeactivating)此思路方法将所需 HttpModule 条目添加到当前 Web 应用 web.config 文件中或从中删除该条目(请参见图 7)图 7 启用和禁用 HttpModule
public override void FeatureActivated(
SPFeatureReceiverProperties properties) {
SPWebApplication WebApp =
(SPWebApplication)properties.Feature.Parent;
WebApp.WebConfigModications.Add(
CreateHttpModuleModication);
WebApp.WebService.ApplyWebConfigModications;
WebApp.WebService.Update;
}
public override void FeatureDeactivating(
SPFeatureReceiverProperties properties) {
SPWebApplication WebApp =
(SPWebApplication)properties.Feature.Parent;
WebApp.WebConfigModications.Remove(
CreateHttpModuleModication);
WebApp.WebService.ApplyWebConfigModications;
WebApp.WebService.Update;
}
在功能激活期间化标记
现在是将所有片段组合到起时候了用户在指定站点集合内激活 LitwareBranding 功能后会出现个功能接收器以及 FeatureActivated 事件处理它将使用 BrandManager 类来应用各种标记元素此外还有个 FeatureDeactivating 事件处理可在功能禁用期间移除所有标记元素(请参见图 8)
图 8 应用和移除标记元素
public override void FeatureActivated(SPFeatureReceiverProperties properties) {
EnsureWebApplicationFeatureEnabled;
BrandManager.ConfigureMasterUrl(true);
BrandManager.ConfigureCustomMasterUrl(true);
BrandManager.ConfigureAlternateCss(true);
BrandManager.ConfigureSiteLogo(true);
BrandManager.ConfigureApplicationPageMaster(true);
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {
BrandManager.ConfigureMasterUrl(false);
BrandManager.ConfigureCustomMasterUrl(false);
BrandManager.ConfigureAlternateCss(false);
BrandManager.ConfigureSiteLogo(false);
BrandManager.ConfigureApplicationPageMaster(false);
}
请注意在 FeatureActivated 事件处理开头部分 EnsureWebApplicationFeatureEnabled 思路方法编写此思路方法是为了确保名为 LitwareBrandingWebApplication Web 应用级功能已被激活以使 HttpModule(它将换出应用页面母版页)在 ASP.NET 中正确注册:public void EnsureWebApplicationFeatureEnabled {
// make sure feature which adds HttpModule to web.config is active
SPSecurity.RunWithElevatedPrivileges(delegate {
using (SPSite siteCollection = SPSite(SPContext.Current.Site.ID)) {
try {
Guid FeatureId = Guid("FF739C76-0B08-4bc2-A3A2-F61524B492D8");
siteCollection.WebApplication.Features.Add(FeatureId);
}
catch { }
}
});
}
创建站点集合范围标记解决方案时WSS 和 MOSS 还会引发另个设计问题:创建子站点时必须决定如何正确地化其标记BrandManager 类中代码只会影响现有站点标记属性因此LitwareBranding 解决方案包括第 3个功能 LitwareBrandingChildSiteInitializer其中包含 FeatureActivated 事件以下事件处理:// fired whenever a site is created
public override void FeatureActivated(SPFeatureReceiverProperties properties) {
SPWeb ChildSite = (SPWeb)properties.Feature.Parent;
SPWeb TopLevelSite = ChildSite.Site.RootWeb;
ChildSite.MasterUrl = TopLevelSite.MasterUrl;
ChildSite.CustomMasterUrl = TopLevelSite.CustomMasterUrl;
ChildSite.AlternateCssUrl = TopLevelSite.AlternateCssUrl;
ChildSite.SiteLogoUrl = TopLevelSite.SiteLogoUrl;
ChildSite.Update;
}
此事件处理在功能激活过程中触发并会将顶级站点标记属性复制到当前子站点中现在您必须考虑如何使该功能在已激活 LitwareBranding 功能站点集合内创建新子站点时自动激活答案是功能装订LitwareBranding 功能提供了个 FeatureSiteTemplateAssociation 元素可将 LitwareBrandingChildSiteInitializer 功能装订到 GLOBAL 站点定义中:
<!-- staple GLOBAL site definition to itwareBrandingChildSiteInitializer -->
<FeatureSiteTemplateAssociation
Id="1204A425-D105-46c5-BB2C-473A2F27B563"
TemplateName="GLOBAL" />
这种装订技术会强制执行自动功能激活通过将 LitwareBrandingChildSiteInitializer 功能装订到 GLOBAL 站点定义中您可以将此功能实际配置为在创建新站点时自动激活而无论使用站点模板是什么请注意名为 Blank Site 标准 WSS 站点模板并不参和对 GLOBAL 站点定义功能装订此行为已被添加到 SharePo 中因此从 Blank Site 模板创建站点将使用 MOSS 内容部署策略如果您要在从 Blank Site 模板创建站点中自动激活 LitwareBrandingChildSiteInitializer 功能必须为该站点定义和配置添加明确装订介绍说明:
<!-- staple blank site template to LitwareBrandingChildSiteInitializer -->
<FeatureSiteTemplateAssociation
Id="1204A425-D105-46c5-BB2C-473A2F27B563"
TemplateName="STS#1" />
最新评论