SOAPAction not obeyed in SPGetCurrentSite

Oct 21, 2011 at 8:31 PM

Hi,

This is my first time using SPService so I apologize if this question seems a little silly.

I've noticed that SPGetCurrentSite does not obey any options set through WSops.WebUrlFromPageUrl.

I'm getting errors returned by the web service that the request header does not contain the appropriate SOAPAction.

A quick check of the source code told me that the Ajax request for SPGetCurrentSite does not contain the "beforesend" option that the SPServices code contains.

beforeSend: function (xhr) {
  // If we need to pass the SOAPAction, do so
  if(WSops[opt.operation][1]) {
    xhr.setRequestHeader("SOAPAction", SOAPAction);
  }
},

Is this by design or is this a bug?

Thanks.

Alfred_j_Kwack

Coordinator
Oct 21, 2011 at 8:38 PM

Alfred:

SPGetCurrentSite works well and has been in SPServices since early on. It's embedded in many of the other functions. I'm not sure what you're passing in, but if you want to call WebUrlFromPageUrl, you should do so directly.

M.

Oct 22, 2011 at 1:42 PM
Edited Oct 24, 2011 at 9:52 AM

OK fine.

Others may accept the difference in behaviour between SPGetCurrentSite and the other methods which all appear to abide the WSops. 

For those that this bothers, here's the change

Original code in v 0.6.2 starting around line 1225

 

	// Function to determine the current Web's URL.  We need this for successful Ajax calls.
	// The function is also available as a public function.
	$.fn.SPServices.SPGetCurrentSite = function() {
		// Do we already know the current site?
		if(thisSite.length > 0) {
			return thisSite;
		}
		
		var msg = SOAPEnvelope.header +
				"<WebUrlFromPageUrl xmlns='http://schemas.microsoft.com/sharepoint/soap/' ><pageUrl>" +
				((location.href.indexOf("?") > 0) ? location.href.substr(0, location.href.indexOf("?")) : location.href) +
				"</pageUrl></WebUrlFromPageUrl>" +
				SOAPEnvelope.footer;
		$.ajax({
			async: false, // Need this to be synchronous so we're assured of a valid value
			url: "/_vti_bin/Webs.asmx",
			type: "POST",
			data: msg,
			dataType: "xml",
			contentType: "text/xml;charset=\"utf-8\"",
			complete: function (xData, Status) {
				thisSite = $(xData.responseXML).find("WebUrlFromPageUrlResult").text();
			}
		});
		return thisSite; // Return the URL
	}; // End $.fn.SPServices.SPGetCurrentSite

 

Patched code:

 

	// Function to determine the current Web's URL.  We need this for successful Ajax calls.
	// The function is also available as a public function.
	$.fn.SPServices.SPGetCurrentSite = function() {
		// Do we already know the current site?
		if(thisSite.length > 0) {
			return thisSite;
		}
		
		$().SPServices({
			operation: "WebUrlFromPageUrl",
			async: false, // Need this to be synchronous so we're assured of a valid value
			pageURL: ((location.href.indexOf("?") > 0) ? location.href.substr(0, location.href.indexOf("?")) : location.href),
			completefunc: function (xData, Status) {
				thisSite = $(xData.responseXML).find("WebUrlFromPageUrlResult").text();
			}
		})
		return thisSite; // Return the URL
	}; // End $.fn.SPServices.SPGetCurrentSite

 

 

Update (24 Oct 2011):

You also need to change the following code around line 350 or you'll get a circular reference:

 

		// Build the URL for the Ajax call based on which operation we're calling
		// If the webURL has been provided, then use it, else use the current site
		var ajaxURL = "_vti_bin/" + WSops[opt.operation][0] + ".asmx";
		if(opt.webURL.charAt(opt.webURL.length - 1) === SLASH) {
			ajaxURL = opt.webURL + ajaxURL;
		} else if(opt.webURL.length > 0) {
			ajaxURL = opt.webURL + SLASH + ajaxURL;
		} else {
			ajaxURL = $().SPServices.SPGetCurrentSite() + SLASH + ajaxURL;
		}

 

to this:

 

		// Build the URL for the Ajax call based on which operation we're calling
		// If the webURL has been provided, then use it, else use the current site
		var ajaxURL = "_vti_bin/" + WSops[opt.operation][0] + ".asmx";
		if(opt.webURL.charAt(opt.webURL.length - 1) === SLASH) {
			ajaxURL = opt.webURL + ajaxURL;
		} else if(opt.webURL.length > 0) {
			ajaxURL = opt.webURL + SLASH + ajaxURL;
		} else if (opt.operation === "WebUrlFromPageUrl") {
			ajaxURL = "/_vti_bin/Webs.asmx";
		} else {
			ajaxURL = $().SPServices.SPGetCurrentSite() + SLASH + ajaxURL;
		}

and then move this code block above line 295 (ie. above the section that starts with "switch(WSops[opt.operation][0]) {"

Not doing so will cause issues as you'll have set the SOAPAction with your original call, then call $().SPServices.SPGetCurrentSite() which may owverwrite your SOAPAction you had in the first place.

Coordinator
Oct 22, 2011 at 1:54 PM

Sorry, I didn't understand your original question fully.

I'm going to have to think about it a little to try to remember why I left it the way I did. What situation have you seen where the current code causes you a problem?

M.

Coordinator
Oct 22, 2011 at 1:59 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Oct 22, 2011 at 2:01 PM

p.s. Truth be told, I think it's just that I added this function so early on and didn't update it when I added the SOAPAction behavior. I think your change is valid. My guess is that you're having problems with anonymous access.

M.

Oct 24, 2011 at 7:25 AM

Hi Marc,

Yes that's correct. Whatever the reason it seems that I have to set the SOAPaction to 'true' on pretty much everything.

Btw. There are a couple more places where SOAPaction is not being accounted for correctly.

Within the "switch(opt.operation)" statement starting at line 363 in v 0.6.2 there are a couple:

      SITEDATA OPERATIONS section:

  • case SiteDataGetListCollection:
    SOAPAction = SOAPAction.replace("SiteDataGetList", "GetList");
  • case SiteDataGetList:
    SOAPAction = SOAPAction.replace("SiteDataGetListCollection", "GetListCollection");