Sp-dev-docs: ClientContext.get_current() in SP.js generates the wrong URL

Created on 27 Feb 2018  路  10Comments  路  Source: SharePoint/sp-dev-docs

Category

  • [ ] Question
  • [ ] Typo
  • [X] Bug
  • [ ] Additional article idea

Expected or Desired Behavior

When using JSOM on a team site, created when creating an O365 Group (via the OWA UI), I expect JSOM to work. Specifically I expect that a call to SP.ClientContext.get_current() generates a usable URL, so one can use the JSOM methods.

Observed Behavior

When adding Web Parts or extensions that use the JSOM (for instance if you want to use the term store) on a team site (coming from an O365 Group) the URL in SP.ClientContext.get_current() is calculated the wrong way. Instead of having the internal url of https.//tenant.sharepoint.com/sites/abc it gets a URL like this https://tenant.sharepoint - as you can see without the .com part. So when JSOM tries to call _api/contextinfo it will throw a 404 error.
However it will work if you go to a site page or similar so the URL ends in https://tenant.sharepoint.com/sites/abc/SitePages/Home.aspx it works as expected.

Steps to Reproduce

  1. Create a O365 Group through the OWA web UI or a Modern Teams site
  2. Go to the site
  3. Paste the following code into the web browser developer toolbar (mimicing what's done in a web part)
_spComponentLoader.loadScript('/_layouts/15/init.js',{globalExportsName: '$_global_init' }).then( () => {
    _spComponentLoader.loadScript('/_layouts/15/MicrosoftAjax.js',{globalExportsName: 'Sys' }).then( () => {
        _spComponentLoader.loadScript('/_layouts/15/SP.Runtime.js',{globalExportsName: 'SP' }).then( () =>  {
            _spComponentLoader.loadScript('/_layouts/15/SP.js',{globalExportsName: 'SP' }).then ( () => {
                console.log('This is the URL:' + window.location.href);
                console.log('This is NOT the URL:' + SP.ClientContext.get_current().$u_0)
            });
        })
    })
})

Example of output.
image

other tracked bug-confirmed

All 10 comments

running into the same issue with 1.4.1, a webpart using MMS (using JSOM because we don't have a REST API ;) ), tenant version 16.0.7625.1209.
Our team site is a modern team site not tied to any group.
Let me know if you need additional data

I have had the same problem with this, using JSOM to connect to Term Store. Everything works out fine on a sitepage url. But with faulty internal url:s it does not seem to be an easy fix with a refreshed context to get around this problem? Does someone have an idea of build a workaround until resolved?

@VesaJuvonen - any updates on this bug?

@VesaJuvonen ??

I found a workaround for this: if the url doesn't contain the page, create a context with the current site:

//----workaround
var clientContext = window.location.pathname.indexOf('.aspx') > -1 ? SP.ClientContext.get_current() : new SP.ClientContext(window.location.pathname);
//----test
var targetWeb = clientContext.get_web();
clientContext.load(targetWeb);
clientContext.executeQueryAsync(()=> console.log(targetWeb));

It is not great but it does the job until the bug is fixed.

@Rafaelki worked like a charm! Thanks

@wictorwilen Does this code work with partial navigation? When the partial navigation occurs it seems webpart code runs before the url updates. If you try to read the path you end up with the url of the page you were previously on, and not the one you are navigating to.

@VesaJuvonen Is there any update on this issue? We are running into problems with Office UI Fabric components that show the same error. And those cannot be easily fixed without forking and modifying them :(

We're getting the same error in our customers' tenancies.

I've had a quick look at SP.debug.js...

Here's the snippet for get_current():

    SP.ClientContext.get_current = function SP_ClientContext$get_current() {
        if (!SP.ClientContext.$2F) {
            var $v_0 = null;
            var $v_1 = window._spPageContextInfo;
            var $v_2 = false;
            if ($v_1) {
                $v_0 = $v_1.webServerRelativeUrl;
            }
            if (SP.ScriptUtility.isNullOrEmptyString($v_0)) {
                $v_0 = window.location.pathname;
                var $v_3 = $v_0.indexOf('?');
                if ($v_3 > 0) {
                    $v_0 = $v_0.substr(0, $v_3);
                }
                $v_3 = $v_0.indexOf('#');
                if ($v_3 > 0) {
                    $v_0 = $v_0.substr(0, $v_3);
                }
                var $v_4 = false;
                var $v_5 = $v_0.toLowerCase();
                var $v_6 = ['/_layouts', '/_vti_bin'];
                for (var $v_7 = 0; $v_7 < $v_6.length; $v_7++) {
                    $v_3 = $v_5.indexOf($v_6[$v_7]);
                    if ($v_3 > 0) {
                        $v_0 = $v_0.substr(0, $v_3);
                        $v_4 = true;
                        break;
                    }
                }
                if (!$v_4) {
                    $v_3 = $v_0.lastIndexOf('.');
                    if ($v_3 > 0) {
                        $v_0 = $v_0.substr(0, $v_3);
                    }
                }
                $v_2 = true;
            }
            SP.ClientContext.$2F = new SP.ClientContext($v_0);
            SP.ClientContext.$2F.set_isPageUrl($v_2);
        }
        return SP.ClientContext.$2F;
    };

Presuming the page is being served from: https://contoso.sharepoint.com/sites/mycollection/sitepages/home.aspx, but made a homepage so that the actual URL in the browser is https://contoso.sharepoint.com/sites/mycollection

...it seems to be this bit that goes wrong:

       if (!$v_4) {
            $v_3 = $v_0.lastIndexOf('.');
            if ($v_3 > 0) {
                $v_0 = $v_0.substr(0, $v_3);
            }
        }

On entry into that block, $v_0 will still be "https://contoso.sharepoint.com/sites/mycollection".

The last index of "." will be just before the ".com", thus breaking the URL. (Of course, if Microsoft were to register a new .sharepoint TLD, that would be awesome...)

Assuming there's not going to be a .sharepoint TLD... then we should probably use window.location.pathname instead.

Swap:

    if (SP.ScriptUtility.isNullOrEmptyString($v_0)) {
        $v_0 = window.location.href;

for:

    if (SP.ScriptUtility.isNullOrEmptyString($v_0)) {
        $v_0 = window.location.pathname;

Any updates on this one?

Cheers!

Joel

Apparently using a new SP.ClientContext() is preferred , and get_Current() is not.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

StfBauer picture StfBauer  路  3Comments

byrongits picture byrongits  路  3Comments

thechriskent picture thechriskent  路  3Comments

zerovectorspace picture zerovectorspace  路  3Comments

jonthenerd picture jonthenerd  路  3Comments