
ASP.NET MVC Integration with Sharepoint 2013. Part 2: Interacting with SharePoint
In a previous article, ASP.NET MVC Integration with Sharepoint 2013. Part 1: High-Trusted provider-hosted APP showed you how to configure SharePoint 2013 for SharePoint Apps (now Microsoft calls it SharePoint Add-in ) and do basic ASP.NET application integration MVC with provider-hosted APP. In this article, I will show how we implemented: searching for SharePoint Site elements in an MVC application, transferring elements from a SharePoint Site, App-parts, and localizing SharePoint elements.
Searching for SharePoint items through an ASP.NET MVC application
Suppose that somewhere in the interface of your application there is a regular search field, which as a result calls action SharepointSearch:
In our case, it was necessary to get all possible references to any SP-objects (by identifier " 0x01 "). However, you can refine the selection of elements using other SharePoint content identifiers.
Attaching SharePoint Elements through CustomActions
Through SharePoint APP, you can "embed" your CustomActions elements in SharePoint (buttons in the ribbon, elements in the context menu). You can read more about how to do this on MSDN .
Let's try to add two elements: a button in the ribbon and in the context menu item.
Let's start with the context menu. To do this, we need to add a new Menu Item Custom Action to our SharePoint APP application.. In the wizard of adding elements, Visual Studio will be asked to choose where and in which lists the context menu item should appear. If you look at the created element, it becomes clear that this is a regular xml file with the following contents:
We will analyze the main elements in order:
RegistrationType & RegistrationId - indicate the combination in which the menu item will be called up (what was indicated in the wizard; can be redefined for a larger range of actions)
Location - where the element is contained (context menu)
Sequence - order in the
Title menu - Visible name. Here you can see that localization has already been applied. This is how elements from Resources (Host web)
UrlAction can be localized - the basis of CustomActions. This is the url where the user will be redirected after the click. In this case, a special system designation is indicated for provider hosted app ~ remoteAppUrl.
It is also important to note the parameters SPListId, SPListItemsId - these are the identifiers of the current sheet and the elements selected in it, respectively. How values are substituted by markers. Full information on the formation of such links can be found here.
Now let's move on to the host action of our MVC application:
Next, with the buttons in the ribbon, you need to do the same thing by adding the Ribbon Custom Action element to the project . Moreover, you can direct the url to the same place, providing in advance that in SPListItemsId there can be several elements separated by a comma. In the code above, this is already provided.
SharePoint AppParts
AppPart is another item that you can install in SharePoint through the App. But in this case, the SharePoint user decides where and where to add this element on the page. The main idea of AppPart is to show part of your high-trusted application using iframe technology. In previous versions of SharePoint, this was also implemented through WebParts.
So, how to add the App-part is also described in detail on MSDN .
You can add his project again using the Visual Studio wizard and is also an xml file of approximately the following contents:
Surely you will need to resize the app part when resizing content. I will leave below javascript code that needs to be called manually when resizing content on the ASP.NET MVC side of the application:
Perhaps this can be finished. Next time I will write how we created our Ribbon Tab, SharePoint Solution and linked it to the SharePoint App.
Searching for SharePoint items through an ASP.NET MVC application
Suppose that somewhere in the interface of your application there is a regular search field, which as a result calls action SharepointSearch:
public JsonResult SharepointSearch(string search)
{
var sharepointItems = GetSharePointSearchResult(search);
var json = JsonHelper.ConvertToJsonResponse(sharepointItems);
return Json(json);
}
private ResponseModel> GetSharePointSearchResult(string query)
{
var responseModel = new ResponseModel>();
var searchResult = new List();
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;
}
In our case, it was necessary to get all possible references to any SP-objects (by identifier " 0x01 "). However, you can refine the selection of elements using other SharePoint content identifiers.
Attaching SharePoint Elements through CustomActions
Through SharePoint APP, you can "embed" your CustomActions elements in SharePoint (buttons in the ribbon, elements in the context menu). You can read more about how to do this on MSDN .
Let's try to add two elements: a button in the ribbon and in the context menu item.
Let's start with the context menu. To do this, we need to add a new Menu Item Custom Action to our SharePoint APP application.. In the wizard of adding elements, Visual Studio will be asked to choose where and in which lists the context menu item should appear. If you look at the created element, it becomes clear that this is a regular xml file with the following contents:
We will analyze the main elements in order:
RegistrationType & RegistrationId - indicate the combination in which the menu item will be called up (what was indicated in the wizard; can be redefined for a larger range of actions)
Location - where the element is contained (context menu)
Sequence - order in the
Title menu - Visible name. Here you can see that localization has already been applied. This is how elements from Resources (Host web)
UrlAction can be localized - the basis of CustomActions. This is the url where the user will be redirected after the click. In this case, a special system designation is indicated for provider hosted app ~ remoteAppUrl.
It is also important to note the parameters SPListId, SPListItemsId - these are the identifiers of the current sheet and the elements selected in it, respectively. How values are substituted by markers. Full information on the formation of such links can be found here.
Now let's move on to the host action of our MVC application:
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 = @"
{0}
";
private void GetSharepointListItemsAndPerformAction(SharePointContext spContext, Guid listId, string listItemIds, Action, 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;
}
}
Next, with the buttons in the ribbon, you need to do the same thing by adding the Ribbon Custom Action element to the project . Moreover, you can direct the url to the same place, providing in advance that in SPListItemsId there can be several elements separated by a comma. In the code above, this is already provided.
SharePoint AppParts
AppPart is another item that you can install in SharePoint through the App. But in this case, the SharePoint user decides where and where to add this element on the page. The main idea of AppPart is to show part of your high-trusted application using iframe technology. In previous versions of SharePoint, this was also implemented through WebParts.
So, how to add the App-part is also described in detail on MSDN .
You can add his project again using the Visual Studio wizard and is also an xml file of approximately the following contents:
Surely you will need to resize the app part when resizing content. I will leave below javascript code that needs to be called manually when resizing content on the ASP.NET MVC side of the application:
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 = ""
+ "resize(" + dwidth + "," + dheight + ") ";
window.parent.postMessage(message, document.referrer);
}
function IsSharepointAppPart() {
return IsInsideIframe();
}
function IsInsideIframe() {
return window.self !== window.top;
}
Perhaps this can be finished. Next time I will write how we created our Ribbon Tab, SharePoint Solution and linked it to the SharePoint App.