SharePointContextFilter 属性无法重建 SharePoint 上下文
SharePointContextFilter attribute fails to rebuild SharePoint context
我开发了一个 SharePoint 加载项 (SharePoint Online),它托管在 Azure 中。该加载项是一个 ASP.NET MVC 应用程序。
情况如下:
/Home/Index:用户从应用程序的登录页面开始,然后转到 Actions
.[=26 部分=]
Actions/Index:在这个页面上,用户必须select一些参数和select一个动作编辑
Actions/Edit/123: 编辑页面打开,显示一个表单,其中所有控件都填写了有关操作的信息。
POST: 更改一些字段后,或者none,用户点击保存按钮。
我没有在列表中显示它,但所有网址都有 SPHostUrl
、SPAppWebUrl
、SPLanguage
、SPClientTag
和 SPProductNumber
参数.
一切正常,除非用户在几分钟内没有与 application/page 交互并且 然后 按下 保存 按钮。按下按钮时,应用程序无法传递 SharePointContextFilter
属性。 SharePointContext 不再 "exist"。以下行 returns 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;
}
因此,如果失败,上下文的创建和保存将失败,应用程序 returns 默认错误页面。
这是调用控制器的 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;
}
为什么这最初有效,但如果用户等待一段时间,代码就无法再次 get/create 上下文?有什么我遗漏的吗?如何解决这个问题?
注意:我知道以下问题: 虽然有有用的信息可供阅读,但对我没有进一步帮助。
This all works fine, except when the user doesn't interact with the application/page for a number of minutes
会话已过期,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;
}
如果你的URL不包含这样的查询参数,你需要修改你的代码,在第一次获取上下文令牌时将上下文令牌存储在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;
}
我开发了一个 SharePoint 加载项 (SharePoint Online),它托管在 Azure 中。该加载项是一个 ASP.NET MVC 应用程序。
情况如下:
/Home/Index:用户从应用程序的登录页面开始,然后转到
Actions
.[=26 部分=]Actions/Index:在这个页面上,用户必须select一些参数和select一个动作编辑
Actions/Edit/123: 编辑页面打开,显示一个表单,其中所有控件都填写了有关操作的信息。
POST: 更改一些字段后,或者none,用户点击保存按钮。
我没有在列表中显示它,但所有网址都有 SPHostUrl
、SPAppWebUrl
、SPLanguage
、SPClientTag
和 SPProductNumber
参数.
一切正常,除非用户在几分钟内没有与 application/page 交互并且 然后 按下 保存 按钮。按下按钮时,应用程序无法传递 SharePointContextFilter
属性。 SharePointContext 不再 "exist"。以下行 returns 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;
}
因此,如果失败,上下文的创建和保存将失败,应用程序 returns 默认错误页面。
这是调用控制器的 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;
}
为什么这最初有效,但如果用户等待一段时间,代码就无法再次 get/create 上下文?有什么我遗漏的吗?如何解决这个问题?
注意:我知道以下问题: 虽然有有用的信息可供阅读,但对我没有进一步帮助。
This all works fine, except when the user doesn't interact with the application/page for a number of minutes
会话已过期,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;
}
如果你的URL不包含这样的查询参数,你需要修改你的代码,在第一次获取上下文令牌时将上下文令牌存储在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;
}