1. App Web & Host Web

The special website to which the app is deployed is called an App Web.

The website to which the app is installed is called the Host Web.

例子:

Suppose, you are developing a SharePoint 2013 app for your organization. In that, you would require the App to access and to use the SharePoint components such as the lists, content types, workflows, and pages. In this Case, all your SharePoint components should be deployed in a separate SharePoint site, called as the App Web.
 
The Host Web is nothing but the SharePoint site where the App is actually installed. So, to conclude, all the resources accessed by a SharePoint web has to be deployed in a different site, named as the App web. And, the actual site where the app is deployed (from VS) is called the Host Web.
 
2. Client Authentication with Office 365
使用SharePointOnlineCredentials对象
ClientContext context = new ClientContext(url);
System.Security.SecureString passWord = new System.Security.SecureString();
foreach (char c in password.ToCharArray())
{
passWord.AppendChar(c);
}
context.Credentials = new SharePointOnlineCredentials(userName, passWord);

3. App中的Client Web Part是否加入到Feature或者package中不影响App中的内容,App文件会将项目中的所有信息加入进去;

4. App的链接中已默认包含了这个参数:SPHostUrl, SPLanguage, SPClientTag, SPProductNumber, 和SPAppWebUrl。

5. 动态创建Tile的方法:

在页面上定义一个container:

<!-- Tiles will be rendered here -->
<div id="tileArea" style="width:600px;"></div>

定义CSS:

/* Custom styles for the tiles */
.tile{
width:150px;
height:150px;
color:#FFFFFF;
margin-top:5px;
margin-left:0px;
margin-right:10px;
margin-bottom:10px;
cursor:pointer;
padding:5px;
float:left;
text-align:right;
font-family:Segoe UI, sans-serif;
font-size:14px;
background-image:url(../images/MetroPlay.png);
background-repeat: no-repeat;
background-position:bottom right;
background-color:#FFAAAA;
}
.tileNumber{
text-align:center;
font-family:Segoe UI Light, sans-serif;
font-size:72px;
margin-top:10px;
margin-bottom:10px;
}
a, a:hover, a:visited {text-decoration:none; outline:none;color:#FFFFFF}
a:active, a:focus {outline:}

使用JavaScript,根据列表数目动态生成tile:

// Variables used to hold objects for use in callback functions
var context;
var lists;
//var list;
var listItems;
var tileArea;
// This code runs when the DOM is ready and creates a context object which is needed
// to use the SharePoint object model
$(document).ready(function () { context = SP.ClientContext.get_current();
var web = context.get_web();
lists = web.get_lists();
context.load(lists);
context.executeQueryAsync(Function.createDelegate(this, renderListTiles), Function.createDelegate(this, errorLoadingLists));
}); function errorLoadingLists(sender, args) {
tileArea = document.getElementById("tileArea"); // Remove all nodes from the chart <DIV> so we have a clean space to write to
while (tileArea.hasChildNodes()) {
tileArea.removeChild(tileArea.lastChild);
} // Write a message to let the user know the operation has failed
var errMessage = document.createElement("div");
errMessage.appendChild(document.createTextNode("Lists could not be retrieved."+args.get_message()));
} function renderListTiles(sender, args) {
var listEnumerator = lists.getEnumerator(); while (listEnumerator.moveNext()) {
var list = listEnumerator.get_current();
var listTitle = list.get_title();
if ((listTitle == "Employees") || (listTitle == "MarketSize") || (listTitle == "Sales")) {
var itemCount = list.get_itemCount();
var tile = document.createElement("a");
tile.setAttribute("class", "tile");
tile.setAttribute("href", "../Lists/" + listTitle);
tile.appendChild(document.createTextNode(listTitle)); $("#tileArea").appendChild(tile);
var tileBody = document.createElement("div");
tileBody.setAttribute("class", "tileNumber");
tileBody.appendChild(document.createTextNode(itemCount.toString()));
tile.appendChild(tileBody);
}
}
}

效果:

6. 向SharePoint Log中添加记录时,需要用到SP.Analytics命名空间(SP.js);

 var eventGuid = new SP.Guid("101c16a5-3abd-4020-921f-cc40090c6ff7");

    // When you have entered a valid GUID, you can then call the logAnalyticsAppEvent
// as follows:
SP.Analytics.AnalyticsUsageEntry.logAnalyticsAppEvent(context, eventGuid, "Test App Page");
context.executeQueryAsync( // This is the success callback:
function () {
status.innerText = "Success! The event for 'Test App Page' has been logged.";
}, // This is the failure callback:
function (sender, e) {
status.innerText = "Failed to log event for 'Test App Page': " + e.get_message();
});

7. sp.userprofiles.js中包含了获取user profle信息的方法和对象(但除了accountName属性,其它属性可能为null)

// This code runs when the DOM is ready and creates a context object
// which is needed to use the SharePoint object model. We also wire
// up the click event handler of the listProfiles button in default.aspx.
$(document).ready(function () {
context = SP.ClientContext.get_current();
$('#listProfiles').click(function () { listProfilesClick();});
}); // This function handles the click event of the listProfiles button in default.aspx
function listProfilesClick() { // Our way into the current user's profile is through the PeopleManager class
// so we'll instantiate a new object and pass in the current context,
peopleMgr = new SP.UserProfiles.PeopleManager(context); // We'll then load the object...
context.load(peopleMgr); // ... and we'll get the user profile properties and load them as well.
profileProperties = peopleMgr.getMyProperties();
context.load(profileProperties); // Next we ask SharePoint to run all of our previously batched commands...
context.executeQueryAsync( // ... and if we're successful, the following success callback will run
function () { if (peopleMgr.get_isMyPeopleListPublic()) {
publicDiv.appendChild(document.createTextNode("Your followers and those you follow are publicly visible"));
}
else {
publicDiv.appendChild(document.createTextNode("Your followers and those you follow are not publicly visible"));
}
$('#profileList').append(publicDiv); // Then we'll add a few simple properties from the profile.
// The first one is the account name
var accountName = profileProperties.get_accountName(); // The second one is the display name.
// Note that we'll check for null in case this property hasn't been set.
var displayName = profileProperties.get_displayName(); // The third thing to show the user is their profile picture.
// Note that we'll check for null in case this property hasn't been set.
// If it's not null, we'll render the actual picture.
var myPicture = profileProperties.get_pictureUrl(); // Finally, we'll add three links:
// One for editing the profile...
var myProfileLink = peopleMgr.get_editProfileLink(); // One for going to the user's personal site...
var myPersonalSite = profileProperties.get_personalUrl(); // And one that shows the user what their page looks like when
// viewed by other users.
var myPublicPersona = profileProperties.get_userUrl(); }, // If we haven't been successful, the following failure callback
// will run, so we'll clear the profile list div, and then use it
// to tell the user what went wrong
function (sender, e) {
$('#profileList').children().remove();
$('#profileList').append(docume.createTextNode(e.get_message()));
});
}

8. SP.RequestExecutor.js文件就是cross-domain library,SP.RequestExecutor对象用于执行与其它数据源交互的操作,比如host-web,app-web;但需要注意的是,如果在APP中使用SP.RequestExecutor对象与Host Web的数据进行交互,由于在App中,默认的context site是app web, 所以我们还需要使用SP.AppContextSite()来设置当前的context site为 host web,然后还要再AppManifest.xml中设置app在host web中的权限(在使用SP.AppContextSite时必须使用SP.AppContextSite(@target) 和?@target='<host web url>'的格式,不能直接将host web地址写在参数括号中);

var hostweburl;
var appWebUrl; // Load the required SharePoint libraries
$(document).ready(function () {
//Get the URI decoded URLs.
hostweburl =
decodeURIComponent(
getQueryStringParameter("SPHostUrl")
); appWebUrl = decodeURIComponent(getQueryStringParameter("SPAppWebUrl")); // Load the js file and continue to the
// success event handler
$.getScript(hostweburl+"/_layouts/15/SP.RequestExecutor.js", execCrossDomainRequest);
}); // Function to prepare and issue the request to get
// SharePoint data
function execCrossDomainRequest() {
var executor; // Initialize the RequestExecutor with the app web URL.
executor = new SP.RequestExecutor("/"); // Issue the call against the host web.
// To get the title using REST we can hit the endpoint:
// app_web_url/_api/SP.AppContextSite(@target)/web/title?@target='siteUrl'
// The response formats the data in the JSON format.
// The functions successHandler and errorHandler attend the
// success and error events respectively.
executor.executeAsync(
{
url:
appWebUrl+"/_api/SP.AppContextSite(@target)/web/title?@target='" +
hostweburl + "'",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: successHandler,
error: errorHandler
}
);
} // Function to handle the success event.
// Prints the host web's title to the page.
function successHandler(data) {
var jsonObject = JSON.parse(data.body); document.getElementById("HostwebTitle").innerHTML =
"<b>" + jsonObject.d.Title + "</b>";
} // Function to handle the error event.
// Prints the error message to the page.
function errorHandler(data, errorCode, errorMessage) {
document.getElementById("HostwebTitle").innerText =
"Could not complete cross-domain call: " + errorMessage;
}

9.  在app中搜索host web内容时,需要在AppManifest.xml文件的Permissions中为app添加Search权限,搜索时使用的url路径就是app web的路径,但依然可以搜索到host web的内容;

function executeQuery() {
alert(_spPageContextInfo.webAbsoluteUrl);
$.ajax(
{
url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?querytext='" + $("#queryTerms").val() + "'",
method: "GET",
headers: {
"Accept": "application/json;odata=verbose"
},
success: onSuccess,
error: onError
}
);
} function onSuccess(data) {
var results = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;
alert(JSON.stringify(data.d.query)); //display json as string
var html = "<table>"; for (var i = 0; i < results.length; i++) {
html += "<tr><td>";
html += results[i].Cells.results[3].Value;
html += "</td><td>"
html += results[i].Cells.results[6].Value;
html += "</td><tr>";
} html += "</table>"; $("#resultsDiv").append($(html));
} function onError(err) {
alert(JSON.stringify(err));
}

10. _spPageContextInfo.webAbsoluteUrl可以直接在app中获取到当前站点的web绝对路径;

11.

SharePoint 2013 - Add-ins的更多相关文章

  1. SharePoint 2013 create workflow by SharePoint Designer 2013

    这篇文章主要基于上一篇http://www.cnblogs.com/qindy/p/6242714.html的基础上,create a sample workflow by SharePoint De ...

  2. SharePoint 2013 configure and publish infopth

    This article will simply descript how to configure and publish a InfoPath step by step. Note: To con ...

  3. Integrating SharePoint 2013 with ADFS and Shibboleth

    Time again to attempt to implement that exciting technology, Federation Services (Web Single Sign On ...

  4. office 365 Sharepoint 2013

    平台环境: office 365 Sharepoint  2013 操作文件和文件夹 访问文档库的最佳方式是借助在 /_api/web 处可用的 GetFolderByServerRelativeUr ...

  5. SharePoint 2013 版本功能对比

    前言:在SharePoint使用中,经常纠结于版本问题,SharePoint 2013主要有免费的Foundation和收费的标准版.企业版三个版本,他们之间的功能上是不一样的,找了一些资料才发现下面 ...

  6. SharePoint 2013 Search REST API 使用示例

    前言:在SharePoint2013中,提供Search REST service搜索服务,你可以在自己的客户端搜索方法或者移动应用程序中使用,该服务支持REST web request.你可以使用K ...

  7. SharePoint 2013 文档库中PPT转换PDF

    通过使用 PowerPoint Automation Services,可以从 PowerPoint 二进制文件格式 (.ppt) 和 PowerPoint Open XML 文件格式 (.pptx) ...

  8. SharePoint 2013 Word 转换PDF服务介绍及示例

    前言:在SharePoint使用过程中,经常会发现将文档进行格式转换的需求,之前,看到SharePoint 2013有将PPT转换PDF文档的服务,后来,才发现SharePoint 2010开始,就有 ...

  9. SharePoint 2013 状态机工作流之UpdateItemActivity

    没什么可说的,一个Activity的使用介绍,其他类似的Activity也可以参考这个使用. 1.添加ApplyActivation和UpdateItemActivity,在onWorkflowAct ...

  10. SharePoint 2013 状态机工作流之日常报销示例

    简单介绍下状态机工作流,状态机工作流提供了一系列的状态.工作流从初始状态开始,到终止状态结束.两个状态之间定义行为进行过渡.通常情况下,状态机工作流对事件作出反应,事件的发生将会使状态发生改变. 1. ...

随机推荐

  1. SDK 开发 .a .framework .bundle (xcode引用) 依赖sdk工程

    一. 静态库.a 1.创建静态库工程 Cocoa Touch Static Libray  ,然后可以创建一个测试视图 TestView 2.暴露头文件 -> Build Phases--> ...

  2. LeetCode231.2的幂

    231.2的幂 描述 给定一个整数,编写一个函数来判断它是否是 2 的幂次方. 示例 示例 1: 输入: 1 输出: true 解释: 2^0 = 1 示例 2: 输入: 16 输出: true 解释 ...

  3. HDU - 1525 博弈 暴力分析

    先来看看比较显然的几个局面 (a,0) 先手必败 (a,a) 先手必胜 (a,ak) 先手必胜 (a,ak+r),k>1 先手必胜,因为先手有主动权把(a,r)让给后手或留给自己 对于开局(a, ...

  4. HibernateUtil hibernate4.0以上

    package com.test.bbs.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import ...

  5. AngularJS 中ng-model通过$watch动态取值

    这个例子的意思是,当xxxx的长度不超过6时,xxxx和yyyy两个input的model是无关的,但当xxxx超过6,则yyyy会跟随其值而变化. 另一种做法是在input的ng-model后面添加 ...

  6. 基于WebImage的图片上传工具类

    支持缩略图和水印. using System; using System.IO; using System.Linq; using System.Web; using System.Web.Helpe ...

  7. js 判断各种数据类型 typeof 几种类型值

    了解js的都知道, 有个typeof  用来判断各种数据类型,有两种写法:typeof   xxx   ,typeof(xxx) 如下实例: typeof   2      输出   number   ...

  8. 通过c++ 读写文本文件的中文乱码的解决方法

    前提:VS2010 ,MFC ,文本文件为ANSI格式. 读文件: CString str,fileContent;CStdioFile myFile, File;if(myFile.Open(Gen ...

  9. 数据挖掘:基于Spark+HanLP实现影视评论关键词抽取(1)

    1. 背景 近日项目要求基于爬取的影视评论信息,抽取影视的关键字信息.考虑到影视评论数据量较大,因此采用Spark处理框架.关键词提取的处理主要包含分词+算法抽取两部分.目前分词工具包较为主流的,包括 ...

  10. nyoj 983 ——首尾相连数组的最大子数组和——————【最大子串和变形】

    首尾相连数组的最大子数组和 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 给定一个由N个整数元素组成的数组arr,数组中有正数也有负数,这个数组不是一般的数组,其首 ...