3

I've had this problem for quite some time and every time I think I've found a clever way around it, it just comes back to haunt me.

We have all kinds of things on all kinds of pages. Many of them need information about the current user. I would prefer if there was a way that could just be pre-populated on the page.

I am currently using a JSOM to request the info and stick it onto a data element on the body tag. But sometimes it is slow and doesn't load before something else on the page needs it.

Is there some way to just always have the masterpage include current user data as part of the page before it gets to the user?

Edit to include current code I can't find the unminified version of the code at the moment, but this is what we are using to get back the basic stuff like user login, name, and email.

$(document).ready(function() {
    function e() {
        var e = new SP.ClientContext.get_current,
            r = e.get_web();
        u = r.get_currentUser(), e.load(u), e.executeQueryAsync(t, n)
    }

    function t() {
        $.data(document.body, "currentUser", u), $("body").trigger("userdata", {
            status: "success",
            data: u
        })
    }

    function n() {
        $("body").trigger("userdata", {
            status: "fail"
        })
    }
    var u;
    null != SP.ClientContext ? SP.SOD.executeOrDelayUntilScriptLoaded(e, "SP.js") : SP.SOD.executeFunc("sp.js", null, e)
});
4
  • What kind of current user data ? Can you post the jsom code as well ? Nov 5, 2016 at 5:46
  • In my case, the first time someone comes to my site I'm doing a sync request to get the user info (name, email, manager) and then I store them into localStorage. So next time those info are immediately available from localStorage. And after 45 seconds on a page I have an async request to update those info (in case something changed with the current user). This method will only work in a work/intranet environment
    – AymKdn
    Nov 6, 2016 at 9:28
  • We are an on prem 2013 site, so that might work, although we do have a lot of users on IE8 so probably can't use localstorage. The part that makes me crazy is that every page has the user's name in the upper right corner. It seems like a minimal amount of user data could just be loaded on to the page and make it easier.
    – Rothrock
    Nov 7, 2016 at 15:38
  • Instead of JSOM (which can only execute after SP.js is loaded) do it with a REST call... and ditch jQuery (which now also needs to load first)... although IE8 (which Microsoft no longer supports since january 12th 2016) might give you some Xhr headaches Nov 7, 2016 at 16:08

2 Answers 2

3

A UserCustomAction Site ScriptLink will fire early on every page (except Modern Experiences).

[links only, no need to duplicate existing documentation]

Disclaimer: you might need to tweak it for IE

This is the simplest bare JavaScript to get the CurrentUser

var xhr = new XMLHttpRequest(); 
xhr.open("GET","/_api/web/CurrentUser", true);
xhr.setRequestHeader("Accept","application/json;odata=verbose");
xhr.onreadystatechange = function (response) {
  if (xhr.readyState != 4) return;//no response received yet 
  if (xhr.status===200) {
      console.info(xhr);
      var currentUser=JSON.parse(xhr.response);
      console.info(currentUser);
  }
};
xhr.send();
10
  • We are using a scriptlink on the masterpage, but sometimes the result of the request doesn't come back quickly enough for other scripts on the page.
    – Rothrock
    Nov 7, 2016 at 15:36
  • See other comment. Your problem is not the response coming back late.. You are querying for your data way to late because it requires jQuery and SP.js be loaded first Nov 7, 2016 at 16:11
  • I'm looking at that page. I don't understand what a UserCustomAction is and where it comes from? All my googls searches for those come back with C# and VB script. My access is just at the Site Collection level. Is that something I can even do?
    – Rothrock
    Nov 7, 2016 at 17:33
  • Doesn't SOP.RequestExecutor have to wait until SP.js loads? I'm not sure this approach would get me anywhere faster.
    – Rothrock
    Nov 7, 2016 at 18:52
  • ?? That is AppWeb/HostWeb technology you are refering to now? But the code you shows has nothing to do with an App... Fastest is to not be dependent on jQuery or any other library. Thus JavaScript HttpRequest (developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/…) BUT its a pain to get it working on IE9 or lower.. that is why jQuery $ajax became so popular. Nov 7, 2016 at 19:34
0

Based on Danny's help and other references, here is the code I've got working in IE8 and IE11, Chrome, and FireFox. Haven't test it on mobile devices yet...

var _currentUser,xhr;

if (window.XMLHttpRequest) {
    try {
        xhr = new XMLHttpRequest();
    } catch (ex) {
        xhr = new window.ActiveXObject("Microsoft.XMLHTTP");
    }
}

xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if(xhr.status == 200){
            var result = JSON.parse(xhr.response || xhr.responseText);
            _currentUser = result.d || result;
        } else if (xhr.status == 400){
            console.log("not found")
        } else {
            console.log("other")
        }
    }
}
xhr.open("GET","https://<site-collection>/_api/web/currentuser",true);
xhr.setRequestHeader("Accept","application/json;odata=verbose")
xhr.send()

Here are a couple of gotchas that I've worked around. - For IE 8 you need the ActiveXObject version of the XMLHttpRequest object. - In IE 8 the reply comes back in the responseText object not in the response. - I tried using XMLHttpRequest.DONE, but that isn't defined for IE8, so I just went with the magic 4 when testing the readyState.

Still looking to improve it.

  • I can't get anything other than odata=verbose to work.
  • I've hard-coded the sitecollection url. I get an error if I try to use _spPageContextInfo.webAbsoluteUrl.
1
  • Don't worry too much about verbose, you only get 300 Bytes more. It does matter when you are going to call an endpoint and you get back loads of Items in a resultset. Also note that verbose versus nometadata gives you back a different resultset structure. And you can do without the path and only call "/_api/web/currentuser" Nov 8, 2016 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.