В предыдущей статье Интеграция 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/
Добавить комментарий