4

I have a Provider hosted app which I use to enter quote data into Sharepoint Office 365. The Host is a MVC C# Webpage.

The action in the controllers all have a similar format like this:

 [SharePointContextFilter] [HttpPost] public ActionResult SaveSOW(int id, string SPHostUrl, bool withCostings = false) { try { var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext); using (var clientContext = spContext.CreateUserClientContextForSPHost()) { var spUser = clientContext.Web.CurrentUser; clientContext.Load(spUser, user => user.Title); clientContext.ExecuteQuery(); var sowRepo = new SOWRepository(clientContext); sowRep.SaveSow(data); //pseudo code } } 

All the actions (besides the entry point) are callled via Jquery AJAX calls.

The problem is, after X minutes when ajax calls a action that is decorated with [SharePointContextFilter] it returns a HTTP 302 (redirect to login) error. I cant ask the usre ot re-login half way through entering a quote (which can take an hour or longer) I have tried doing clientContext:

 clientContext.RequestTimeout = Timeout.Infinite; 

with no success.

I have also tried adding a loop with Javascript to keep hitting an action in the controller with [SharePointContextFilter]

 GetRefreshToken: function () { $.ajax({ url: "/Refresh/RefreshToken?" + window.location.href.slice(window.location.href.indexOf('?') + 1), type: "GET", success: function (data) { console.log(data) }, error: function (data) { console.log("Error refreshing token", data); } }) 

after a while it still sends the AJAX refresh request to appredirect.aspx

My Refresh Action is just:

[SharePointContextFilter] [HttpGet] public ActionResult RefreshToken() { var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext); using (var clientContext = spContext.CreateUserClientContextForSPHost()) { if (clientContext != null) { return Json("Token Refreshed", JsonRequestBehavior.AllowGet); } } return Json("Token NOT Refreshed", JsonRequestBehavior.AllowGet); } 

}

5
  • Are you passing the SPHostUrl in the ajax request? Commented Feb 23, 2017 at 12:56
  • yes I am, like so: url: "/Quote/UpdateCOS?" + window.location.href.slice(window.location.href.indexOf('?') + 1), Commented Feb 24, 2017 at 10:15
  • 1
    I had this issue myself awhile back. The problem is that the SPContextToken that the ACS server returns has expiry date that's just over an hour after you get it. Since the SharePointContext class checks that token in the SharePointContextFilter, it sees that it's expired, and requires a postback to the ACS server (via the AppRedirect Url). I ended up writing my own token helper to get the Refresh and Access tokens, and I cache the Refresh token (good for 6 months at this time) in session. Commented Feb 24, 2017 at 15:57
  • You can just modify the SharePointContext class to do the same. I went down that road initially, but was annoyed with how they wrote the class, so decided to rewrite the whole thing. Commented Feb 24, 2017 at 15:58
  • thanks wjervis, you solved my problem. I ended up storing the refresh key in httpcontext.session and using it when contexttoken expires. i might write up a fulll answer when i finish Commented Feb 25, 2017 at 0:47

2 Answers 2

2

Thanks to wjervis for giving me the solution. The problem was because the Oauth2 Access token was expiring and to my suprise the supplied SharePointContext classes do not rerfresh.

I hacked together a solution and blogged it here. Its definitely not the most elegant solution, but it'll point you in the right direction.

URL REMOVED

update Thanks to Microsoft closing SharePoint Public sites (which is what I used to host my blog on) I have now moved my blog to here:

https://www.sharepointpro.com.au/blog/sharepoint-provider-hosted-app-redirects-after-timeout/

7
  • 1
    I think that this problem should be reported to Microsoft and they should fix SharePointContext class, because it seems that refresh token is not used properly. Commented Feb 25, 2017 at 15:39
  • I ended up writing my own set of classes to handle the entire OAUTH dance and caching of the tokens. If I was more confident with my abilities, I'd post them here. Commented Feb 26, 2017 at 18:28
  • this is the route I will go down eventually. half way through editing the SharePointContext I realised how much cleaner it would be to just start from scratch. Commented Feb 27, 2017 at 0:42
  • 2
    I'm unable to navigate to sharepointpro.com.au/Blog/Post/26/… asking me sign in Commented Jul 28, 2017 at 5:13
  • The link is now a 404 page Commented Aug 5, 2017 at 21:53
0

You can try to create some empty GET controller action with [SharePointContextFilter] attribute and call it periodically using JavaScript. This should prevent token expiration.

2
  • This was my first idea, unfortunately it didn't work either. Ill update the original question Commented Feb 24, 2017 at 10:16
  • @michael any update on above pls? Commented Jul 28, 2017 at 5:21

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.