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)
});
  • What kind of current user data ? Can you post the jsom code as well ? – Gautam Sheth Nov 5 '16 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 '16 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 '16 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 – Danny '365CSI' Engelman Nov 7 '16 at 16:08
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();
  • 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 '16 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 – Danny '365CSI' Engelman Nov 7 '16 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 '16 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 '16 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. – Danny '365CSI' Engelman Nov 7 '16 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.
  • 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" – Danny '365CSI' Engelman Nov 8 '16 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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