Поделиться через


Замена файлов SharePoint, развернутых с помощью модулей в решениях фермы

Если вы декларативно развертывали файлы с помощью модулей в решениях фермы, узнайте, как преобразовать их в новые решения, которые обновляют ссылки на файлы и предоставляют аналогичные функции с помощью клиентской объектной модели (CSOM). В прошлом модули использовались для развертывания таких файлов, как master страницы и макеты страниц.

Важно!

Решения фермы нельзя перенести в SharePoint Online. Применяя методы и код, описанные в этой статье, можно создать новое решение с аналогичными функциями, которые предоставляют решения фермы, обновить ссылки на файлы, а затем развернуть новое решение в SharePoint Online. Затем вы можете отключить эту функцию и отозвать предыдущее решение фермы.

Код, приведенный в этой статье, требует дополнительного кода, чтобы обеспечить полностью работающее решение. Например, в этой статье не рассматривается проверка подлинности с помощью Office 365, реализация необходимой обработки исключений и т. д. Дополнительные примеры кода см. в проекте шаблоны и методики разработчика Office 365.

Примечание.

Код, приведенный в этой статье, предоставляется "как есть" без какой-либо явной или подразумеваемой гарантии, включая подразумеваемые гарантии пригодности для какой-либо цели, для продажи или гарантии отсутствия нарушения прав иных правообладателей.

В этой статье описывается, как использовать процесс преобразования для:

  • Отправка и обновление ссылок на страницы master
  • Отправка и обновление ссылок на макеты страниц

Используйте этот процесс преобразования, если:

  • Существующие решения фермы использовали модули для развертывания файлов.
  • Вы хотите заменить master страницы и макеты страниц в решениях ферм новыми master страницами и макетами страниц, чтобы их можно было перенести в SharePoint Online.
  • Вы декларативно настроили типы содержимого документов на master страницах или макетах страниц в решении фермы.

Подготовка к работе

В идеале следует просмотреть существующие решения фермы, узнать о методах, описанных в этой статье, а затем спланировать применение этих методов в своих сценариях. Если вы не знакомы с решениями фермы или у вас нет существующего решения фермы для работы, вам может быть полезно узнать о решениях фермы.

Дополнительные сведения см. в статье Создание решений фермы в SharePoint.

Включение функций публикации в семействе веб-сайтов и на сайте

Перед выполнением примера кода включите функции публикации в семействе веб-сайтов и на сайте, выполнив следующие процедуры.

Включение функции инфраструктуры публикации SharePoint Server в семействе веб-сайтов

  1. Откройте сайт SharePoint и перейдите в раздел Параметры>Параметры сайта.

  2. В разделе Администрирование семейства веб-сайтов выберите Функции семейства веб-сайтов.

  3. На вкладке Инфраструктура публикации SharePoint Server выберите Активировать.

Включение функции публикации SharePoint Server на сайте

  1. Откройте сайт SharePoint и перейдите в раздел Параметры>Параметры сайта.

  2. В разделе Действия сайта выберите Управление функциями сайта.

  3. В публикации SharePoint Server нажмите кнопку Активировать.

Настройка проекта Visual Studio

  1. Скачайте пример проекта. Выберите Просмотр необработанного , чтобы начать загрузку примера проекта, извлечь файлы из ZIP-файла, а затем перейдите в папку Module9/ModuleReplacement.

  2. Откройте ModuleReplacement.sln.

  3. Откройте settings.xml. Просмотрите и обновите следующие атрибуты в соответствии со своими требованиями:

    • Элемент masterPage — использует атрибут file для указания новой страницы master для развертывания в коллекции главных страниц, а атрибут replaces — для указания существующей страницы master в коллекции главных страниц.

    • Элемент pageLayout — использует атрибут file для указания нового файла макета страницы, атрибут replaces для указания существующего файла макета страницы и несколько других атрибутов для указания дополнительных сведений о макете страницы.

     	<?xml version="1.0" encoding="utf-8" ?>
     	<branding>
     	  <masterPages>
     	       <masterPage file="contoso_app.master" replaces="contoso.master"/>
     	  </masterPages>
     	  <pageLayouts>
     	       <pageLayout file="ContosoWelcomeLinksApp.aspx" replaces="ContosoWelcomeLinks.aspx" title="Contoso Welcome Links add-in" associatedContentTypeName="Contoso Web Page" defaultLayout="true" />
     	  </pageLayouts>
     	</branding>
    
    
  4. В файле MasterPageGalleryFiles.cs классы MasterPageGalleryFile и LayoutFile определяют бизнес-объекты, в которые хранятся сведения о новых master страницах и макетах страниц для отправки в SharePoint.

Отправка и обновление ссылок на страницы master

Чтобы отправить и обновить ссылки на новые страницы master на сайте SharePoint, выполните следующие действия:

  1. В файле Program.cs добавьте следующую инструкцию using .

     	using System.Security;
    
  2. В файле Program.cs добавьте следующие методы для выполнения проверки подлинности для Office 365.

static SecureString GetPassword()
      {
          SecureString sStrPwd = new SecureString();
          try
          {
              Console.Write("Password: ");

              for (ConsoleKeyInfo keyInfo = Console.ReadKey(true); keyInfo.Key != ConsoleKey.Enter; keyInfo = Console.ReadKey(true))
              {
                  if (keyInfo.Key == ConsoleKey.Backspace)
                  {
                      if (sStrPwd.Length > 0)
                      {
                          sStrPwd.RemoveAt(sStrPwd.Length - 1);
                          Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
                          Console.Write(" ");
                          Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
                      }
                  }
                  else if (keyInfo.Key != ConsoleKey.Enter)
                  {
                      Console.Write("*");
                      sStrPwd.AppendChar(keyInfo.KeyChar);
                  }

              }
              Console.WriteLine("");
          }
          catch (Exception e)
          {
              sStrPwd = null;
              Console.WriteLine(e.Message);
          }

          return sStrPwd;
      }

      static string GetUserName()
      {
          string strUserName = string.Empty;
          try
          {
              Console.Write("Username: ");
              strUserName = Console.ReadLine();
          }
          catch (Exception e)
          {
              Console.WriteLine(e.Message);
              strUserName = string.Empty;
          }
          return strUserName;
      }
  1. В Файле Program.cs добавьте следующий код в метод Main , который выполняет следующие задачи:

    1. Загружает файл settings.xml.

    2. Возвращает ссылку на коллекцию главных страниц с помощью GetCatalog (116).

      Главные страницы отправляются в коллекцию главных страниц. Идентификатор шаблона списка коллекции главных страниц — 116. Дополнительные сведения см. в разделе Элемент ListTemplate (Site). Загружаются другие сведения о коллекции главных страниц, в том числе с помощью List.ContentTypes для получения типов контента, связанных с коллекцией эталонных страниц.

    3. Загружает свойства веб-объекта, включая Web.ContentTypes, Web.MasterUrl и Web.CustomMasterUrl.

    4. Задает parentMasterPageContentTypeId для идентификатора типа контента master страниц. Дополнительные сведения см. в статье Base Content Type Hierarchy.

    5. Возвращает тип контента master страниц из коллекции главных страниц. Этот тип контента используется для задания типа контента новой страницы master далее в этой статье.

       static void Main(string[] args)
       	{ 
       		string userName = GetUserName();
       		SecureString pwd = GetPassword();
      
       	// End program if no credentials were entered.
       		if (string.IsNullOrEmpty(userName) || (pwd == null))
       		return;
      
       		using (var clientContext = new ClientContext("http://sharepoint.contoso.com"))
       		{
      
       			clientContext.AuthenticationMode = ClientAuthenticationMode.Default;
       			clientContext.Credentials = new SharePointOnlineCredentials(userName, pwd);
      
       			XDocument settings = XDocument.Load("settings.xml");
      
       			// Get a reference to the Master Page Gallery which will be used to upload new master pages. 
      
       			Web web = clientContext.Web;
       			List gallery = web.GetCatalog(116);
       			Folder folder = gallery.RootFolder;
      
       			// Load additional Master Page Gallery properties.
       			clientContext.Load(folder);
       			clientContext.Load(gallery,
       								g => g.ContentTypes,
       								g => g.RootFolder.ServerRelativeUrl);
      
       			// Load the content types and master page information from the web.
       			clientContext.Load(web,
       								w => w.ContentTypes,
       								w => w.MasterUrl,
       								w => w.CustomMasterUrl);
       			clientContext.ExecuteQuery();
      
       			// Get the content type for the master page from the Master Page Gallery using the content type ID for masterpages (0x010105).
       			const string parentMasterPageContentTypeId = "0x010105";  
       			ContentType masterPageContentType = gallery.ContentTypes.FirstOrDefault(ct => ct.StringId.StartsWith(parentMasterPageContentTypeId));
       			UploadAndSetMasterPages(web, folder, clientContext, settings, masterPageContentType.StringId);
      
       		}
      
       	}
      
  2. В Program.cs добавьте метод UploadAndSetMasterPages , который создает список бизнес-объектов MasterPageGalleryFile , выполнив следующие действия:

    1. Чтение всех элементов masterPage, определенных в settings.xml.

    2. Для каждого элемента masterPage, который указывает master страницу для отправки в SharePoint, загрузив значения атрибутов в бизнес-объект MasterPageGalleryFile.

    3. Для каждого бизнес-объекта MasterPageGalleryFile в списке, выполняя вызов UploadAndSetMasterPage.

      
       private static void UploadAndSetMasterPages(Web web, Folder folder, ClientContext clientContext, XDocument settings, string contentTypeId)
       {
       	IList<MasterPageGalleryFile> masterPages = (from m in settings.Descendants("masterPage")
       												select new MasterPageGalleryFile
       												{
       													File = (string)m.Attribute("file"),
       													Replaces = (string)m.Attribute("replaces"),
       													ContentTypeId = contentTypeId
       												}).ToList();
       	foreach (MasterPageGalleryFile masterPage in masterPages)
       	{
       		UploadAndSetMasterPage(web, folder, clientContext, masterPage);
       	}
       }
      
  3. В Program.cs добавьте метод UploadAndSetMasterPage , который выполняет следующие задачи:

    1. Извлекает страницу master.

    2. Отправляет новый файл с помощью FileCreationInformation.

    3. Возвращает элемент списка, связанный с только что отправленным файлом.

    4. Задает различные свойства элемента списка, включая задание идентификатора типа контента элемента списка идентификатором типа контента master страницы.

    5. Возвращает, публикует и утверждает новую страницу master.

    6. Если для текущей страницы master сайта или URL-адреса настраиваемой master страницы задана старая master страница, обновите Web.MasterUrl илиWeb.CustomMasterUrl, чтобы использовать только что отправленный URL-адрес master страницы.

       private static void UploadAndSetMasterPage(Web web, Folder folder, ClientContext clientContext, MasterPageGalleryFile masterPage)
       {
       	using (var fileReadingStream = System.IO.File.OpenRead(masterPage.File))
       	{
       		// If necessary, ensure that the master page is checked out.
       		PublishingHelper.CheckOutFile(web, masterPage.File, folder.ServerRelativeUrl);
      
       // Use the FileCreationInformation class to upload the new file.
       		var fileInfo = new FileCreationInformation();
       		fileInfo.ContentStream = fileReadingStream;
       		fileInfo.Overwrite = true;
       		fileInfo.Url = masterPage.File;
       		File file = folder.Files.Add(fileInfo);
      
       // Get the list item associated with the newly uploaded master page file.
       		ListItem item = file.ListItemAllFields;
       		clientContext.Load(file.ListItemAllFields);
       		clientContext.Load(file,
       							f => f.CheckOutType,
       							f => f.Level,
       							f => f.ServerRelativeUrl);
       		clientContext.ExecuteQuery();
      
       item["ContentTypeId"] = masterPage.ContentTypeId;
       		item["UIVersion"] = Convert.ToString(15);
       		item["MasterPageDescription"] = "Master Page Uploaded using CSOM";
       		item.Update();
       		clientContext.ExecuteQuery();
      
       // If necessary, check in, publish, and approve the new master page file. 
       		PublishingHelper.CheckInPublishAndApproveFile(file);
      
       // On the current site, update the master page references to use the new master page. 
       		if (web.MasterUrl.EndsWith("/" + masterPage.Replaces))
       		{
       			web.MasterUrl = file.ServerRelativeUrl;
       		}
       		if (web.CustomMasterUrl.EndsWith("/" + masterPage.Replaces))
       		{
       			web.CustomMasterUrl = file.ServerRelativeUrl;
       		}
       		web.Update();
       		clientContext.ExecuteQuery();
       	}
       }
      

Отправка и обновление ссылок на макеты страниц

Примечание.

Примеры кода в этом разделе создаются на основе примеров кода, приведенных в предыдущем разделе этой статьи.

Чтобы заменить макеты страниц, развернутые с помощью модулей в решениях фермы, а также отправить и обновить ссылки для использования новых файлов макета страницы:

  1. Обновите метод Main , используя следующий код. Этот код содержит дополнительные шаги для отправки и обновления ссылок на файлы макета страницы, в том числе:

    1. Задав parentPageLayoutContentTypeId идентификатор типа контента макета страницы.

    2. Получение типа контента, соответствующего parentPageLayoutContentTypeId из коллекции эталонных страниц.

    3. Вызов UploadPageLayoutsAndUpdateReferences.

       			static void Main(string[] args)
       	{ 
       		string userName = GetUserName();
       		SecureString pwd = GetPassword();
      
       	// End program if no credentials were entered.
       		if (string.IsNullOrEmpty(userName) || (pwd == null))
       		return;
      
       		using (var clientContext = new ClientContext("http://sharepoint.contoso.com"))
       		{
      
       			clientContext.AuthenticationMode = ClientAuthenticationMode.Default;
       			clientContext.Credentials = new SharePointOnlineCredentials(userName, pwd);
      
       			XDocument settings = XDocument.Load("settings.xml");
      
       			// Get a reference to the Master Page Gallery, which will be used to upload new master pages. 
      
       			Web web = clientContext.Web;
       			List gallery = web.GetCatalog(116);
       			Folder folder = gallery.RootFolder;
      
       			// Load additional Master Page Gallery properties. 
       			clientContext.Load(folder);
       			clientContext.Load(gallery,
       								g => g.ContentTypes,
       								g => g.RootFolder.ServerRelativeUrl);
      
       			// Load the content types and master page information from the web.
       			clientContext.Load(web,
       								w => w.ContentTypes,
       								w => w.MasterUrl,
       								w => w.CustomMasterUrl);
       			clientContext.ExecuteQuery();
      
       			// Get the content type for the master page from the Master Page Gallery using the content type ID for masterpages (0x010105).
       			const string parentMasterPageContentTypeId = "0x010105";  
       			ContentType masterPageContentType = gallery.ContentTypes.FirstOrDefault(ct => ct.StringId.StartsWith(parentMasterPageContentTypeId));
       			UploadAndSetMasterPages(web, folder, clientContext, settings, masterPageContentType.StringId);
      
       		// Get the content type ID for the page layout, and then update references to the page layouts.
       		const string parentPageLayoutContentTypeId = "0x01010007FF3E057FA8AB4AA42FCB67B453FFC100E214EEE741181F4E9F7ACC43278EE811"; 
       		ContentType pageLayoutContentType = gallery.ContentTypes.FirstOrDefault(ct => ct.StringId.StartsWith(parentPageLayoutContentTypeId));
       		UploadPageLayoutsAndUpdateReferences(web, folder, clientContext, settings, pageLayoutContentType.StringId);
       		}
      
       	}
      
  2. В Файле Program.cs добавьте метод UploadPageLayoutsAndUpdateReferences , который выполняет следующие действия:

    1. Считывает сведения о замене макета страницы, считывая элементы страницы из settings.xml, сохраняя сведения о замене макета страницы в бизнес-объектах LayoutFile и добавляя все бизнес-объекты в список.

    2. Для замены каждого макета страницы:

      • Запрашивает типы контента сайта с помощью Web.ContentTypes для поиска соответствующего типа контента, в котором имя типа контента сайта равно свойству associatedContentTypeName , указанному в settings.xml для нового макета страницы.

      • Вызывает UploadPageLayout.

      • Вызывает UpdatePages для обновления существующих страниц, чтобы использовать новые макеты страниц.

           		private static void UploadPageLayoutsAndUpdateReferences(Web web, Folder folder, ClientContext clientContext, XDocument settings, string contentTypeId)
           {
           	// Read the replacement settings stored in pageLayout elements in settings.xml.
           	IList<LayoutFile> pageLayouts = (from m in settings.Descendants("pageLayout")
           								select new LayoutFile
           								{
           									File = (string)m.Attribute("file"),
           									Replaces = (string)m.Attribute("replaces"),
           									Title = (string)m.Attribute("title"),
           									ContentTypeId = contentTypeId,
           									AssociatedContentTypeName = (string)m.Attribute("associatedContentTypeName"),
           									DefaultLayout = m.Attribute("defaultLayout") != null &amp;&amp; (bool)m.Attribute("defaultLayout")
           								}).ToList();
           // Update the content type association.
           			foreach (LayoutFile pageLayout in pageLayouts)
           	{
           		ContentType associatedContentType =
           			web.ContentTypes.FirstOrDefault(ct => ct.Name == pageLayout.AssociatedContentTypeName);
           		pageLayout.AssociatedContentTypeId = associatedContentType.StringId;                
           		UploadPageLayout(web, folder, clientContext, pageLayout);
           	}
        
           			UpdatePages(web, clientContext, pageLayouts);
           		}
        
        
  3. В Program.cs добавьте метод UploadPageLayout , который выполняет следующие задачи:

    1. Извлекает файл макета страницы.

    2. Отправляет новый файл с помощью FileCreationInformation.

    3. Возвращает элемент списка, связанный с только что отправленным файлом.

    4. Задает различные свойства элемента списка, включая ContentTypeId и PublishingAssociatedContentType.

    5. Возвращает, публикует и утверждает новый файл макета страницы.

    6. Чтобы удалить ссылки на старый файл макета страницы, вызывает метод PublishingHelper.UpdateAvailablePageLayouts , чтобы обновить XML-файл, хранящийся в свойстве PageLayouts на текущем сайте.

    7. Если значение атрибута defaultLayout недавно отправленного файла макета страницы из settings.xml имеет значение true, использует PublishingHelper.SetDefaultPageLayout для обновления XML-файла, хранящегося в свойстве DefaultPageLayout на текущем сайте.

       private static void UploadPageLayout(Web web, Folder folder, ClientContext clientContext, LayoutFile pageLayout)
       {
       	using (var fileReadingStream = System.IO.File.OpenRead(pageLayout.File))
       	{
       		PublishingHelper.CheckOutFile(web, pageLayout.File, folder.ServerRelativeUrl);
       		// Use FileCreationInformation to upload the new page layout file.
       		var fileInfo = new FileCreationInformation();
       		fileInfo.ContentStream = fileReadingStream;
       		fileInfo.Overwrite = true;
       		fileInfo.Url = pageLayout.File;
       		File file = folder.Files.Add(fileInfo);
       		// Get the list item associated with the newly uploaded file.
       		ListItem item = file.ListItemAllFields;
       		clientContext.Load(file.ListItemAllFields);
       		clientContext.Load(file,
       							f => f.CheckOutType,
       							f => f.Level,
       							f => f.ServerRelativeUrl);
       		clientContext.ExecuteQuery();
      
       item["ContentTypeId"] = pageLayout.ContentTypeId;
       		item["Title"] = pageLayout.Title;
       		item["PublishingAssociatedContentType"] = string.Format(";#{0};#{1};#", pageLayout.AssociatedContentTypeName, pageLayout.AssociatedContentTypeId);
       		item.Update();
       		clientContext.ExecuteQuery();
      
       PublishingHelper.CheckInPublishAndApproveFile(file);
      
       PublishingHelper.UpdateAvailablePageLayouts(web, clientContext, pageLayout, file);
      
       if (pageLayout.DefaultLayout)
       		{
       			PublishingHelper.SetDefaultPageLayout(web, clientContext, file);
       		}
       	}
       }
      
  4. В Program.cs добавьте метод UpdatePages , который выполняет следующие задачи:

    1. Возвращает библиотеку Pages , а затем получает все элементы списка в библиотеке Pages .

    2. Для каждого элемента списка использует поле PublishingPageLayout элемента списка, чтобы найти соответствующий макет страницы для обновления, который был указан в settings.xml и теперь хранится в страницах со страницами . Если необходимо обновить поле PublishingPageLayout элемента списка, чтобы сослаться на новый макет страницы:

      • Извлекает файл элемента списка с помощью PublishingHelper.CheckOutFile.

      • Обновления URL-адрес макета страницы для ссылки на новый файл макета страницы, а затем обновляет поле PublishingPageLayout элемента списка.

      • Возвращает, публикует и утверждает файл, на который ссылается элемент списка.

           private static void UpdatePages(Web web, ClientContext clientContext, IList<LayoutFile> pageLayouts)
           {
           	// Get the Pages Library, and then get all the list items in it.
           	List pagesList = web.Lists.GetByTitle("Pages");
           	var allItemsQuery = CamlQuery.CreateAllItemsQuery();
           	ListItemCollection items = pagesList.GetItems(allItemsQuery);
           	clientContext.Load(items);
           	clientContext.ExecuteQuery();
           	foreach (ListItem item in items)
           	{
           		// Only update those pages that are using a page layout which is being replaced.
           		var pageLayout = item["PublishingPageLayout"] as FieldUrlValue;
           		if (pageLayout != null)
           		{
           			LayoutFile matchingLayout = pageLayouts.FirstOrDefault(p => pageLayout.Url.EndsWith("/" + p.Replaces));
           			if (matchingLayout != null)
           			{
           				// Check out the page so that we can update the page layout. 
           				PublishingHelper.CheckOutFile(web, item);
        
           // Update the pageLayout reference.
           				pageLayout.Url = pageLayout.Url.Replace(matchingLayout.Replaces, matchingLayout.File);
           				item["PublishingPageLayout"] = pageLayout;
           				item.Update();
           				File file = item.File;
        
           // Get the file and other attributes so that you can check in the file.
           				clientContext.Load(file,
           					f => f.Level,
           					f => f.CheckOutType);
           				clientContext.ExecuteQuery();
        
           				PublishingHelper.CheckInPublishAndApproveFile(file);
           			}
           		}
           	}
           }
        

См. также