If you launch a SharePoint/Office365 provider hosted addin using a direct URL to the app, rather than using the site contents page/applauncher, either as a dialog or fullpage immersive – you may notice that after your addin displays in the browser, the page is automatically reloaded.
First, in this scenario because you [probably] won’t have an access token, nor a context token, the MVC SharePointContext filter will redirect you back to the SharePoint site hosting the addin, specifically the AppRedirect.aspx page.
The AppRedirect.aspx page, after taking care of authentication, will POST you back to your addin with the SPHasRedirectedToSharePoint=1 querystring value.
At this point, you’re back in your addin and alls well and good, except that by default, your MVC addin will include the spcontext.js file, which is provided by project wizard.
This file is trying to be helpful, by adding the SPHostUrl
querystring values to <A/>
elements found on your page.
What it also does is remove the SPHasRedirectedToSharePoint=1 from the browser URL by modifying window.location.search
. It does this to ensure that bookmarks to the addin are set correctly and don’t include this querystring value.
Unfortunately, changing window.location.search
also causes the browser to reload the page.
There is a simple fix for this, which is to use the session history management capability provided by modern browsers (not IE 9 and below) which allows you to modify the browser URL without causing a page reload.
You can get an updated spcontext.js from the gist below, the changes are at the end of the file in the ensureSPHasRedirectedToSharePointRemoved()
function.
(function (window, undefined) { | |
"use strict"; | |
var $ = window.jQuery; | |
var document = window.document; | |
// SPHostUrl parameter name | |
var SPHostUrlKey = "SPHostUrl"; | |
// Gets SPHostUrl from the current URL and appends it as query string to the links which point to current domain in the page. | |
$(document).ready(function () { | |
ensureSPHasRedirectedToSharePointRemoved(); | |
var spHostUrl = getSPHostUrlFromQueryString(window.location.search); | |
var currentAuthority = getAuthorityFromUrl(window.location.href).toUpperCase(); | |
if (spHostUrl && currentAuthority) { | |
appendSPHostUrlToLinks(spHostUrl, currentAuthority); | |
} | |
}); | |
// Appends SPHostUrl as query string to all the links which point to current domain. | |
function appendSPHostUrlToLinks(spHostUrl, currentAuthority) { | |
$("a") | |
.filter(function () { | |
var authority = getAuthorityFromUrl(this.href); | |
if (!authority && /^#|:/.test(this.href)) { | |
// Filters out anchors and urls with other unsupported protocols. | |
return false; | |
} | |
return authority.toUpperCase() == currentAuthority; | |
}) | |
.each(function () { | |
if (!getSPHostUrlFromQueryString(this.search)) { | |
if (this.search.length > 0) { | |
this.search += "&" + SPHostUrlKey + "=" + spHostUrl; | |
} | |
else { | |
this.search = "?" + SPHostUrlKey + "=" + spHostUrl; | |
} | |
} | |
}); | |
} | |
// Gets SPHostUrl from the given query string. | |
function getSPHostUrlFromQueryString(queryString) { | |
if (queryString) { | |
if (queryString[0] === "?") { | |
queryString = queryString.substring(1); | |
} | |
var keyValuePairArray = queryString.split("&"); | |
for (var i = 0; i < keyValuePairArray.length; i++) { | |
var currentKeyValuePair = keyValuePairArray[i].split("="); | |
if (currentKeyValuePair.length > 1 && currentKeyValuePair[0] == SPHostUrlKey) { | |
return currentKeyValuePair[1]; | |
} | |
} | |
} | |
return null; | |
} | |
// Gets authority from the given url when it is an absolute url with http/https protocol or a protocol relative url. | |
function getAuthorityFromUrl(url) { | |
if (url) { | |
var match = /^(?:https:\/\/|http:\/\/|\/\/)([^\/\?#]+)(?:\/|#|$|\?)/i.exec(url); | |
if (match) { | |
return match[1]; | |
} | |
} | |
return null; | |
} | |
// If SPHasRedirectedToSharePoint exists in the query string, remove it. | |
// Hence, when user bookmarks the url, SPHasRedirectedToSharePoint will not be included. | |
// Note that modifying window.location.search will cause an additional request to server. | |
function ensureSPHasRedirectedToSharePointRemoved() { | |
var SPHasRedirectedToSharePointParam = "&SPHasRedirectedToSharePoint=1"; | |
var queryString = window.location.search; | |
if (queryString.indexOf(SPHasRedirectedToSharePointParam) >= 0) { | |
if (window.history.pushState) { | |
var safeUrl = window.location.pathname + queryString.replace(SPHasRedirectedToSharePointParam, ''); | |
window.history.pushState(null, document.title, safeUrl); | |
} else { | |
window.location.search = queryString.replace(SPHasRedirectedToSharePointParam, ""); | |
} | |
} | |
} | |
})(window); |
Published by