Интеграция ASP.NET MVC c Sharepoint 2013. Part 2: Взаимодействие с SharePoint

от автора

В предыдущей статье Интеграция ASP.NET MVC c Sharepoint 2013. Part 1: High-Trusted provider-hosted APP было разобрано, как настроить SharePoint 2013 для SharePoint Apps (теперь Microsoft называет это SharePoint Add-in) и сделать базовую интеграцию приложения ASP.NET MVC с provider-hosted APP. В этой статье я покажу, как мы реализовали: поиск элементов SharePoint Site в MVC приложении, передачу элементов из SharePoint Site, App-parts и локализацию элементов SharePoint.

Поиск элементов SharePoint через ASP.NET MVC приложение

Допустим, что где-то в интерфейсе вашего приложения есть обычное поисковое поле, которое в результате вызывает action SharepointSearch:

    public JsonResult SharepointSearch(string search)     {         var sharepointItems = GetSharePointSearchResult(search);         var json = JsonHelper.ConvertToJsonResponse(sharepointItems);          return Json(json);     }      private ResponseModel<List<SharePointDocumentModel>> GetSharePointSearchResult(string query)     {         var responseModel = new ResponseModel<List<SharePointDocumentModel>>();         var searchResult = new List<SharePointDocumentModel>();          var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);          if (spContext == null)         {             responseModel.Initialize(searchResult, Resources.SharepointContextNull, ResponseStatusEnum.Fail);             return responseModel;         }                          using (var clientContext = spContext.CreateUserClientContextForSpHost())         {             clientContext.ExecuteQuery();              var keywordQuery = new KeywordQuery(clientContext);             keywordQuery.QueryText = query;              var searchExecutor = new SearchExecutor(clientContext);              var results = searchExecutor.ExecuteQuery(keywordQuery);             clientContext.ExecuteQuery();             foreach (var resultRow in results.Value[0].ResultRows)             {                 clientContext.ExecuteQuery();                 var spDocument = new SharePointDocumentModel();                 DateTime createdDateTime;                 DateTime.TryParse(GetDictonaryStringValueByKey(resultRow, "Write"), out createdDateTime);                  var contentTypeId = spDocument.DocumentName = GetDictonaryStringValueByKey(resultRow, "ContentTypeId");                  if (contentTypeId.StartsWith("0x01"))                 {                     spDocument.DocumentName = GetDictonaryStringValueByKey(resultRow, "Title");                     spDocument.DocumentUrl = GetDictonaryStringValueByKey(resultRow, "Path");                     spDocument.Id = GetDictonaryStringValueByKey(resultRow, "WorkId");                     spDocument.Author = GetDictonaryStringValueByKey(resultRow, "Author");                                          spDocument.CreateDate = createdDateTime.ToShortDateString();                      searchResult.Add(spDocument);                 }             }         }          responseModel.Initialize(searchResult);          return responseModel;     } 

В нашем случае необходимо было получить все возможные ссылки на любые SP-объекты (по идентификатору "0x01"). Однако вы можете детализировать отбор элементов, используя другие идентификаторы контента SharePoint

Присоединение элементов SharePoint через CustomActions

Через SharePoint APP вы можете «внедрить» в SharePoint свои элементы CustomActions (кнопки в риббоне, элементы в контекстном меню). Подробней о том, как это делать, можно прочитать на MSDN.
Попробуем добавить два элемента: кнопку в риббон и в пункт контекстное меню.
Начнем с контекстного меню. Для этого нам потребуется добавить в наш SharePoint APP приложение новый Menu Item Custom Action. В визарде добавления элементов Visual Studio будет предложено выбрать, где и в каких списках должен появляться пункт контекстного меню. Если взглянуть на созданный элемент, то станет понятно, что это обычный xml файл следующего содержания:

<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/">   <CustomAction Id="6d471c89-41cc-4b81-b794-ea7664dc4c38.AttachToNewDocument"                 RegistrationType="ContentType"                 RegistrationId="0x0101"                 Location="EditControlBlock"                 Sequence="10001"                 Title="$Resources:ContextMenu_AttachToNewDocument">      <UrlAction Url="~remoteAppUrl/Navigator/SharepointAction/?SPHostUrl={HostUrl}&SPListId={ListId}&SPListItemsId={ItemId}" />   </CustomAction> </Elements> 

Разберем по порядку основные элементы:
RegistrationType & RegistrationId — указывают комбинацию, при которой пункт меню будет вызываться (то, что было указано в визарде; можно переопределить на больший спектр действия)
Location — где элемент содержится (контекстное меню)
Sequence — порядок в меню
Title — Видимое название. Здесь можно увидеть, что уже применена локализация. Именно так можно локализовать элементы из Resources (Host web)
UrlAction — основа CustomActions. Здесь указывается url, куда будет перенаправлен пользователь после клика. В данном случае указано специальное системное обозначение для provider hosted app ~remoteAppUrl.
Также важно отметить параметры SPListId, SPListItemsId — это идентификаторы текущего листа и выбранных в нем элементов соответственно. Как значения подставлены маркеры. Полную информацию по формированию таких ссылок можно найти здесь

Теперь перейдем к принимающему action нашего MVC приложения:

    public ActionResult SharepointAction(SharepointActionModel actionModel)     {         var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);           GetSharepointListItemsAndPerformAction(spContext, actionModel.SpListId.Value, actionModel.SpListItemsId,             (listItems, ids, context, spList) =>             {                 if (spList.BaseType == BaseType.DocumentLibrary)                 {                     richCardId = AttachSharepointDocumentsToDocumentCard(listItems, ids, context);                 }             });           return Redirect(model.UrlToNavigate);     }      public class SharepointActionModel     {         public Guid? SpListId { get; set; }          public string SpListItemsId { get; set; }          public string SpHostUrl { get; set; }     }      private const string DocumentCamlQuery = @"<QueryOptions><ViewAttributes Scope='All'/></QueryOptions>                                                 <Where>                                                     <In>                                                         <FieldRef Name='ID' />                                                         <Values>                                                             {0}                                                         </Values>                                                     </In>                                                 </Where>";      private void GetSharepointListItemsAndPerformAction(SharePointContext spContext, Guid listId, string listItemIds, Action<ListItemCollection, List<int>, ClientContext, List> fileAction)     {         try         {             if (spContext == null)                 throw Error.SharepointIntergration();              using (var clientContext = spContext.CreateUserClientContextForSPHost())             {                 var spList = clientContext.Web.Lists.GetById(listId);                 clientContext.Load(spList);                 clientContext.ExecuteQuery();                                  if (spList != null && spList.ItemCount > 0)                 {                     var camlQuery = new CamlQuery();                     camlQuery.ViewXml = String.Format(DocumentCamlQuery, GetFilterValues(listItemIds));                      var listItems = spList.GetItems(camlQuery);                      clientContext.Load(listItems);                     clientContext.ExecuteQuery();                      var stringIds = listItemIds.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);                     var ids = ConvertToIntFromStringIds(stringIds);                      fileAction(listItems, ids, clientContext, spList);                 }             }         }         catch (Exception ex)         {             Trace.TraceError(ex);             throw;         }     } 

Далее, с кнопками в риббоне необходимо сделать все то же самое, добавив в проект элемент Ribbon Custom Action. Причем можно направить url в то же самое место, заранее предусмотрев, что в SPListItemsId может быть несколько элементов, разделенных запятой. В коде выше это уже предусмотрено.

SharePoint AppParts

AppPart — еще один элемент, который можно установить в SharePoint через App. Но в данном случае пользователь SharePoint сам решает, где и куда добавить этот элемент на странице. Основная идея AppPart — показать часть вашего high-trusted приложения, используя технологию iframe. В предыдущих версиях SharePoint это же было реализовано через WebParts.

Итак, как добавлять App-part подробно описано тоже на MSDN.
Добавить его проект можно снова, используя визард Visual Studio и представляет из себя тоже xml файл примерно следующего содержания:

<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/">   <ClientWebPart Name="Approvals" Title="$Resources:AppPart_Approvals_Title" Description="$Resources:AppPart_Approvals_Description" DefaultWidth="850" DefaultHeight="150">     <Content Type="html" Src="~remoteAppUrl/Navigator/ApprovalAppPart?{StandardTokens}" />   </ClientWebPart> </Elements> 

Наверняка потребуется менять размеры app part при изменении размера контента. Я оставлю ниже javascript код, который необходимо вызывать вручную при изменении размера контента на стороне ASP.NET MVC приложения:

    function ResizeIFrame() {         if (!IsSharepointAppPart())             return;          var oBody = document.body;         var innerHeight = $(".app-part-content", oBody).height();          var dheight = innerHeight + (oBody.offsetHeight - oBody.clientHeight);         var dwidth = oBody.scrollWidth + (oBody.offsetWidth - oBody.clientWidth);          var message = "<Message senderId=" + senderId + " >"             + "resize(" + dwidth + "," + dheight + ")</Message>";         window.parent.postMessage(message, document.referrer);     }      function IsSharepointAppPart() {         return IsInsideIframe();     }      function IsInsideIframe() {         return window.self !== window.top;     } 

Пожалуй, на этом можно закончить. В следующий раз я напишу, как мы создали свой Ribbon Tab, SharePoint Solution и связали его c SharePoint App.

ссылка на оригинал статьи http://habrahabr.ru/post/269499/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *