65.9K
CodeProject 正在变化。 阅读更多。
Home

SharePoint 自定义预配提供程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (5投票s)

2011 年 4 月 21 日

CPOL

8分钟阅读

viewsIcon

47096

downloadIcon

571

关于站点创建方法和使用自定义预配提供程序的讨论

引言

在 SharePoint 中,有多种创建网站的方法,每种方法都有其优点和缺点。自定义网站部署提供程序被许多人认为是创建自定义 SharePoint 网站的最佳方法。在这篇简短的文章中,我将演示如何创建和使用自定义网站部署提供程序。

背景

本文中的示例使用了 SharePoint Server 2010,尽管这些技术也适用于 Microsoft Office SharePoint Server 2007。

创建网站的多种方法

在 SharePoint 中,有多种方法可以创建自定义网站定义:网站模板、网站定义和网站部署提供程序。

网站模板

Microsoft SharePoint 可由具有适当权限和授权的最终用户进行高度配置;这就是它的设计初衷。用户可能花费大量时间配置包含列表、页面和视图的网站,并希望将其复制到其他环境中。这时网站模板就很有用了。

要创建网站模板,请转到“网站操作 -> 网站设置”,然后在“网站操作”标题下,单击“另存为模板”链接。

image1.PNG

显示的页面将要求输入文件名、模板名称和描述,以及是否包含内容。填写此信息并单击“确定”按钮后,SharePoint 将此网站打包为 WSP 文件,并附带适当的配置文件,然后将其放置在解决方案库中。从此,它可用于在网站集内创建新网站。要将模板用于其他网站集,您必须转到“解决方案库”并将模板保存到外部位置,即您的硬盘驱动器,然后在另一个网站集中上传并激活该模板在“解决方案库”中。

以上所有过程都可以由开发人员和场管理员介入完成。但是,这种方法也有缺点。

使用网站模板并不是真正可重用的解决方案。是的,它可以保存并上传到不同的网站集,但它可能依赖于其他网站集不存在的功能或安全性。使用“包含内容”选项时,您还受 10MB 的限制,如果网站仅用于结构创建,这还可以,但如果它使用了大量需要功能的列表项,那您就无能为力了。网站模板也不支持项级安全性,因此在从模板创建新网站后,可能需要重置所有安全性。

网站模板打包为 WSP,使用 Visual Studio 2010,可以将其导入到新项目中。但是,它会带来大量无关的附加信息。

image2.PNG

尽管您可以选择或取消选择您想要的元素,但其中一些确实存在依赖关系,您需要将它们导入项目才能完成。

image3.PNG

网站定义

网站定义是 SharePoint 的基础,在从内置模板创建网站时使用。如上所述,保存网站模板时也会创建自定义网站定义。由于有许多资源涵盖 SharePoint 网站定义,我将不详细介绍,只为本次讨论提供一些要点。

网站定义由一个 `Onet.xml` 文件组成;我在下面包含了一个基本版本。有关此文件的更多信息可以在此处找到。

<?xml version="1.0" encoding="utf-8"?>
<Project Title="SiteDefinitionProject1" 
         Revision="2" 
         ListDir="" 
         xmlns:ows="Microsoft SharePoint" 
         xmlns="http://schemas.microsoft.com/sharepoint/">
  <NavBars>
  </NavBars>
  <Configurations>
    <Configuration ID="0" Name="SiteDefinitionProject1">
      <Lists/>
      <SiteFeatures>
      </SiteFeatures>
      <WebFeatures>
      </WebFeatures>
      <Modules>
        <Module Name="DefaultBlank" />
      </Modules>
    </Configuration>
  </Configurations>
  <Modules>
    <Module Name="DefaultBlank" Url="" Path="">
      <File Url="default.aspx">
      </File>
    </Module>
  </Modules>
</Project>

正如您所看到的,`Onet.xml` 中可以包含大量信息,用于定义网站的创建方式及其将使用的功能。您可以定义网站使用的列表模板、导航元素以及站点页面等文件。该文件还描述了需要在网站和 Web 级别激活的任何功能。

尽管这种方法多年来一直与 SharePoint 一起使用,并且内置网站模板也使用此方法,但它有一个显著的缺点。对网站定义的任何更改都会影响使用该定义创建的所有网站。为了说明这一点,请生成并部署本文代码下载中提供的 CPSiteDef 解决方案,并使用此定义添加一个新网站。在创建网站案例后,主页应如下所示

image4.PNG

现在,在 Visual Studio 项目中,展开“网站定义”模块并打开 `default.aspx` 页面,添加或修改任何您想要的文本。当您重新部署解决方案并刷新页面时,您应该会看到所做的更改。

image5.PNG

您无需创建另一个使用该模板的网站即可看到此更改,它将自动更新所有网站。显然,这可能会产生一些非常不受欢迎和意外的影响。

网站部署提供程序

提供创建新网站机制的新推荐方法是使用自定义网站部署提供程序。

当然,首先我们需要在 Visual Studio 中创建一个新的空 SharePoint 2010 项目。然后,向该项目添加一个代码文件,并使其派生自 `SPWebProvisioningProvider`。此基类有一个需要实现的方法,即 `Provision`。

public class CPSiteProvider : SPWebProvisioningProvider
{
    public override void Provision(SPWebProvisioningProperties props)
    {
        throw new NotImplementedException();
    }
}

当然,无论使用网站定义还是自定义部署提供程序(如本例),都必须有一个 `webtemp*` 文件,以便 SharePoint 能够识别并使模板可用。有关此文件的详细信息可以在此处找到。但对于本次讨论,关键点是 `ProvisioningAssembly`、`ProvisioningClass` 和 `ProvisionData` 属性。

<?xml version="1.0" encoding="utf-8" ?>
<Templates>
  <Template Name="CPSiteProvider" ID="25001">
    <Configuration
		ID="0"
		Title="Code Project Site Provisioning Provider"
		Hidden="false"
		ImageUrl="/_layouts/images/CPSiteProvider/CP_Logo.gif"
		Description="A demonstration or using a custom Site 
				Provisioning Provider"
		DisplayCategory="Code Project"
		ProvisionAssembly="$SharePoint.Project.AssemblyFullName$"
		ProvisionClass="CPSiteProvider.ProvisioningProvider"
		ProvisionData="TEMPLATE\FEATURES\
		CPSiteProvider_SiteData\ProvisioningData\CPSiteProvider.xml"
		SubWebOnly="TRUE">
    </Configuration>
  </Template>
</Templates>

对于 `ProvisioningAssembly`,我们将只使用内置的 Visual Studio 宏,它会在项目生成时扩展为正确的四部分条目。`ProvisioningClass` 是实现 `SPWebProvisioningProvider` 的类的完全限定名称,在本例中为 `ProvisioningProvider`。`ProvisionData` 属性用于指定部署提供程序所需的任何额外数据。在这种情况下,我使用的是相对于 SharePoint 根文件夹的 XML 文件的路径,该文件将包含其他信息。

部署提供程序是一个空白画布,除非被告知,否则不会创建任何内容。考虑到这一点,我们将首先使用 `SPWeb` 对象的 `ApplyWebTemplate` 方法来创建一个空白网站作为开始。如您所见,`web` 是传递到 `Provision` 方法的 `SPWebProvisioningProperties` 属性中可用的属性之一。另一个属性是 `Data`,它将包含我们在 `webtemp` 文件中指定的 `ProvisionData` 属性的值,我们将稍后利用它。

private const string SITE_TEMPLATE = "STS#1";

public override void Provision(SPWebProvisioningProperties props)
{
    // Create a blank site to begin from
    props.Web.ApplyWebTemplate(SITE_TEMPLATE);
}

现在基本网站已创建,我们将添加必要的特性来适当地配置我们的网站。

public override void Provision(SPWebProvisioningProperties props)
{
    // Create a blank site to begin from
    props.Web.ApplyWebTemplate(SITE_TEMPLATE);

    // Save this so it is available in other methods
    Properties = props;

    SPSecurity.CodeToRunElevated code = 
		new SPSecurity.CodeToRunElevated(CreateSite);
    SPSecurity.RunWithElevatedPrivileges(code);
}

private void CreateSite()
{
    using(SPSite site = new SPSite(Properties.Web.Site.ID))
    {
        using(SPWeb web = site.OpenWeb(Properties.Web.ID))
        {
            // Add specified features to this site
            AddSiteFeatures(site);

            // Add specified features to this web
            AddWebFeatures(web);

            // Add new default page
            AddDefaultPage(web);
        }
    }
}

由于网站可以由任何人创建,因此我们需要确保拥有适当的安全权限,这就是 `SPSecurity.RunWithElevatedPrivileges` 有用的地方。这将使任何在其上下文中运行的代码都以 Web 应用程序 `AppPool` 的凭据执行。尽管您可以使用匿名委托来使用此方法,但为了提高可读性和可维护性,我将创建一个 `SPSecurity.CodeToRunElevated` 对象并分配一个要运行的方法。这有一个小问题,该方法的委托不接受任何参数。为了能够访问 `SPWebProvisioningProperties`,我将其分配给一个 `private` 属性。

在 `AddSiteFeatures` 方法中,首先要做的是访问包含我们希望在此站点中启用的特性的 XML 文件。由于路径是相对的,我们需要找到 `SharePoint` 根文件夹。尽管它通常是 `"%Program Files%\Common Files\Microsoft Shared\Web Server Extensions\14"`,但作为优秀的开发人员,我们不能依赖它,而应专门查询对象模型以获取正确的路径。这在 `DataFile` 属性中使用 `SPUtility.GetGenericSetupPath` 方法完成。

private void AddSiteFeatures(SPSite site)
{
    List<xelement> features = (from f in DataFile.Elements("SiteFeatures")
                        .Elements("Feature")
                            select f).ToList();

    foreach(XElement feature in features)
    {
        // Make sure the feature hasn't already been activated
        SPFeature f = site.Features[new Guid(feature.Attribute("ID").Value)];
        if(f == null)
        {
            site.Features.Add(new Guid(feature.Attribute("ID").Value));
        }
    }
}

private XElement DataFile
{
    get
    {
        XElement featuresXml = null;
        if(Properties != null)
        {
            // Construct the path from the SharePoint root folder to
            // the file specified in the webtemp
            string path = SPUtility.GetGenericSetupPath
			(Path.GetDirectoryName(Properties.Data));
            path = Path.Combine(path, Path.GetFileName(Properties.Data));

            // Load the xml file
            featuresXml = XElement.Load(path);
        }

        return featuresXml;
    }
}
</xelement>

获取 XML 文件后,只需将指定的特性添加到站点或 Web 即可。我使用了与网站定义项目相同的特性,以便进行比较,但您可以添加任何其他需要的特性。此时也可以将任何列表或其他项添加到网站。

这种方法的好处是网站直到运行时才创建,并且不像网站定义方法那样依赖于文件系统中的文件。为了进行精确比较,我们需要包含 `default.aspx` 页面。

private void AddDefaultPage(SPWeb web)
{
    string file = (from f in DataFile.Elements("DefaultPage")
                    select f).Single().Attribute("file").Value;

    string filePath = FeaturePath + "\\" + file;
    TextReader reader = new StreamReader(filePath);

    MemoryStream outStream = new MemoryStream();
    StreamWriter writer = new StreamWriter(outStream);

    writer.Write(reader.ReadToEnd());
    writer.Flush();

    web.Files.Add("Default.aspx", outStream, true);
}

在这里您可以看到,我们从部署文件中提取了将使用的 `Default.aspx` 页面的路径,然后将文件的内容读入 `Stream` 并将其写回 `StreamWriter`。在 `SPWeb.Files.Add` 方法中使用 `true` 将允许现有 `Default.aspx` 页面被我们的新文件覆盖。由于这会将页面添加到内容数据库,因此它现在是非托管的,因此独立于文件系统中的文件。

您可以像以前一样测试此过程。基于此模板创建新网站。在 Visual Studio 项目中更新 `default.aspx` 页面并重新部署解决方案。如果刷新页面,您将看不到任何更改。如果您创建一个新网站,那么将使用修改后的 `default.aspx` 页面。

结论

本文旨在解释在 SharePoint 中创建和应用网站模板的不同方法以及它们各自的优缺点。希望这能让读者对选择最适合项目的方法有一个很好的理解。

历史

  • 首次发布:11/04/21
© . All rights reserved.