我开发了一个SharePoint加载项(SharePoint Online),它托管在Azure中。该加载项是一个ASP.NET MVC应用程序。
以下是这种情况:
/主页/索引:用户在应用程序的登录页面上启动,然后转到Actions
部分。
操作/索引:在此页面上,用户必须选择一些参数并选择要编辑的操作
操作/编辑/ 123 :系统会打开一个表单,其中会显示一个表单,其中包含有关操作的信息。
发布:更改某些字段后,或者没有,用户点击保存按钮。
我没有在列表中显示它,但所有网址都包含SPHostUrl
,SPAppWebUrl
,SPLanguage
,SPClientTag
& SPProductNumber
参数。
这一切都运行正常,除非用户没有与应用程序/页面进行数分钟的交互,然后按保存按钮。按下按钮时,应用程序无法传递SharePointContextFilter
属性。 SharePointContext没有"存在"了。以下行返回 null :
SharePointContext spContext = LoadSharePointContext(httpContext);
通常情况下,如果它不存在或不存在,代码将尝试根据请求创建它。在CreateSharePointContext
方法中,contextTokenString
始终为 null :
string contextTokenString = TokenHelper.GetContextTokenFromRequest(httpRequest);
这是方法的代码:
public static string GetContextTokenFromRequest(HttpRequestBase request)
{
string[] paramNames = { "AppContext", "AppContextToken", "AccessToken", "SPAppToken" };
foreach (string paramName in paramNames)
{
if (!string.IsNullOrEmpty(request.Form[paramName]))
{
return request.Form[paramName];
}
if (!string.IsNullOrEmpty(request.QueryString[paramName]))
{
return request.QueryString[paramName];
}
}
return null;
}
因此,如果失败,则创建和保存上下文失败,应用程序返回默认错误页面。
这是调用控制器的jQuery代码:
var request = $.ajax({
url: '@Url.Action("Edit", "Actions")' + window.buildSpAppParameters(),
data: $("#updateForm").serialize(),
cache: false,
type: "POST"
});
这是buildSpAppParameters
函数的代码:
function buildSpAppParameters() {
var spHostUrl = getQueryStringParameter("SPHostUrl");
var appWebUrl = getQueryStringParameter("SPAppWebUrl");
var spLanguage = getQueryStringParameter("SPLanguage");
var spClientTag = getQueryStringParameter("SPClientTag");
var spProductNr = getQueryStringParameter("SPProductNumber");
return "?SPHostUrl=" + spHostUrl +
"&SPAppWebUrl=" + appWebUrl +
"&SPLanguage=" + spLanguage +
"&SPClientTag=" + spClientTag +
"&SPProductNumber=" + spProductNr;
}
为什么这最初有效,但如果用户等了一段时间,代码就无法再次获取/创建上下文?有什么我想念的东西,怎么能解决这个问题?
注意:我知道以下问题:Sharepoint 2013 MVC 5 provider-hosted app. Fails to authenticate on HttpPost using [SharePointContextFilter]虽然有一些有用的信息需要阅读,但它并没有帮助我。
答案 0 :(得分:1)
这一切都很好,除非用户没有与应用程序/页面进行数分钟的交互
会话已过期且SharePointContext已丢失。所以我们需要重新生成上下文。
根据GetContextTokenFromRequest方法,应在查询字符串或表单中传递上下文标记。但是从buildSpAppParameters方法中,我们发现上下文令牌是从查询字符串传递的。查询字符串参数应命名为AppContext或AppContextToken或AccessToken或SPAppToken。
要解决此问题,您可以检查浏览器中的当前URL是否包含名为AppContext或AppContextToken或AccessToken或SPAppToken的查询参数。如果是,您可以从URL读取此参数的值,并在buildSpAppParameters方法中传递它。例如,如果您的URL包含名为AppContextToken的查询参数,则可以按如下方式修改代码。
function buildSpAppParameters() {
var spHostUrl = getQueryStringParameter("SPHostUrl");
var appWebUrl = getQueryStringParameter("SPAppWebUrl");
var spLanguage = getQueryStringParameter("SPLanguage");
var spClientTag = getQueryStringParameter("SPClientTag");
var spProductNr = getQueryStringParameter("SPProductNumber");
var appContextToken = getQueryStringParameter("AppContextToken");
return "?SPHostUrl=" + spHostUrl +
"&SPAppWebUrl=" + appWebUrl +
"&SPLanguage=" + spLanguage +
"&SPClientTag=" + spClientTag +
"&SPProductNumber=" + spProductNr +
"&AppContextToken=" + appContextToken;
}
如果您的网址不包含此类查询参数,则需要修改代码,以便在第一次获取上下文令牌时将上下文令牌存储在Cookie中。
string contextTokenString = TokenHelper.GetContextTokenFromRequest(httpRequest);
if (!string.IsNullOrEmpty(contextTokenString))
{
HttpCookie cookie = new HttpCookie("AppContextToken", contextTokenString);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
}
之后,如果令牌没有通过查询字符串传递,则可以从cookie获取上下文令牌。
public static string GetContextTokenFromRequest(HttpRequestBase request)
{
string[] paramNames = { "AppContext", "AppContextToken", "AccessToken", "SPAppToken" };
foreach (string paramName in paramNames)
{
if (!string.IsNullOrEmpty(request.Form[paramName]))
{
return request.Form[paramName];
}
if (!string.IsNullOrEmpty(request.QueryString[paramName]))
{
return request.QueryString[paramName];
}
}
if (request.Cookies["AppContextToken"] != null)
{
return request.Cookies["AppContextToken"].Value;
}
return null;
}