Don’t Use a Query String Parameter Called ID Unless You Mean the Item ID

The other day I got a question from my pal D’arce Hess (@DarceHess):

I am using jsLink on a couple lists and I have an interesting circumstance I’m running into.

Scenario: I have a list of Work Centers and each work center has associated machines that are in another list.

I’m having an interesting situation that when I click on the link in the Work Center, it is supposed to reload the same page and append the Work Center ID to the url  so that it will load the associated machines in the other list. I have the functionality working, however for some reason, when it adds the ID and reloads the page, it is changing the page layout from the layout that is chosen for the initial .aspx page.

Since it is literally re-loading the same page, just with an additional ID, I’m not creating new pages. Any ideas of what may be causing this?

After some back and forth about it, I realized that D’arce was using a query string parameter named “ID”. (I know, it should have been obvious to me right away, but we have a way of using shorthand when we describe technical issues that always makes a little back and forth useful.)

ID seems to be very reserved in SharePoint. Someone probably left some sort of back door thing in SharePoint once a long time ago, because I’ve seen using the ID parameter on the query string for anything other than the item ID cause issues way back to SharePoint 2007 at least.

By switching from ID to WorkCenter for the parameter name, all was right in the world again. For example, instead of “ID=1”, “WorkCenter=1”. Not only does this fix the issue, you end up with a query string parameter name that is more descriptive. That’s useful down the road for maintenance and will even make more sense to users. “That URL is ugly” may become “Oh, I’m selecting the WorkCenter”.

Refreshing a Web Part Without a Postback Using jQuery’s AJAX Function

I’ve been working on several projects with good old SharePoint 2007 (MOSS). jQuery and jQueryUI sure can spice it up nicely. Recently, I decided I wanted to refresh the contents of a Data View Web Part (DVWP) based on a user selection – a simple click on one of a big set of links – but I wanted to avoid that clunky postback.

SharePoint 2010 has the ManualRefresh capability baked right into DVWPs, but not SharePoint 2007. Besides, I wanted both the trigger for the refresh and the UX to work differently than the rather utilitarian (and never used in my experience) out of the box feel that 2010 gives you.

This is the script I came up with. In this case, I decided to show a nice message in a modal dialog using jQueryUI while I waited for the .ajax() call to complete, as I’m using an AggregateDataSource that is querying several pretty large lists. This means it takes a few seconds to come back, and the dialog saying what’s going on – not just a spinner – makes the UX more palatable.

Refreshes an element's contents on a user action, showing a modal dialog during the refresh
elementId  The id of the container element
qs         The Query String to append to the current URL
title      The title to show for the dialog
msg        The message to show in the dialog

function refreshElement(elementId, qs, title, msg) {

  var elementObj = $("#" + elementId);
  var infoDialog = $("<div><div>" + msg + "</div><div class='aaa-please-wait'></div></div>").dialog({
    open: function(event, ui) {
      $(".ui-dialog-titlebar-close").hide();  // Hide the close X
      $(this).css("overflow-y", "visible");   // Fix for the scrollbar in IE
    autoOpen: false,
    title: title,
    modal: true

  elementObj.fadeOut("slow", function() {
      async: false,
      url: window.location.pathname + qs,
      complete: function (xData) {
        newHtml = $(xData.responseText).find("#" + elementId).html();
  }).fadeIn("slow", function() {

I made the function pretty generic so that I could pass in the four arguments and use it in multiple locations if I needed to. You could really pass in the id of any element in the page. In the instance I built it for, I was passing a new value on the Query String based on what link the user clicked on, but fetching the same page with AJAX. The DVWP was set up to return different data based on the Query String parameter value.

Keep in mind that both jQuery and jQueryUI must be loaded for this to work.

The CSS for the body of the dialog is pretty simple, but here it is. The sizing worked well for me based on the image I decided to display.

.aaa-please-wait {
  background-position:center center;

What do you think? Would this make a good addition to SPServices? If so, what other options would you like me to include? If I did add it to SPServices, I’d remove the dependency on jQueryUI, as I don’t want any outside dependencies other than jQuery itself.

Enhanced by Zemanta

Using SPServices & jQuery to Clone a Parent Item and All Its Children: Comments on Mark Rackley’s Post

Mark Rackley (@mrackley) is definitely earning the salary I’m paying him as the Marketing Manager for SPServices.  (Yes, that salary is zero.) He posted another great article about Using SPServices & jQuery to Clone a Parent Item and All its Children today, and I wanted to point out a few things about it. I’m not dissing Mark in any way: his article is excellent. There are just a few things I’d suggest. ;+)

  • On Mark’s “batches’ comment, I haven’t done testing to determine the optimal numbers there, either. However, the constraints are very different, since you are asking the client machines to do the processing. The important thing is to know what the *worst* configuration might be in your user base and consider it for testing.
  • There’s a function in SPServices called $().SPServices.SPGetQueryString that will do the Query String parsing for you.
  • Always use the minified version of your jQuery libraries if you can; they are “squished” to send the fewest bytes down the wire. e.g., jquery.SPServices-0.5.8.min.js instead of jquery.SPServices-0.5.8.js.
  • I think it’s a bug in the Lists Web Service, but even when you specify just the Title in the CAMLViewFields as Mark has, you still get all of the mandatory columns, *even* if you specify IncludeMandatoryColumns=”false” in the queryOptions. It’s usually no big deal, but it makes calls to GetListItems where there are a lot of items returned less efficient than you might expect.
  • JavaScript gives you a little shorthand for adding text to a string. Instead of this:
                updateXML = updateXML + "<Method ID='" + index++ + "' Cmd='New'>" +
                        "<Field Name='Title' Type='String'>" + title  +  "</Field>" +
                        "<Field Name='Entry_x0020_Date' Type='Date'>" + entryDate +  "</Field>" +
                        "<Field Name='Hours' Type='Number'>" + hours +  "</Field>" +
                        "<Field Name='IssueID' Type='Number'>" + newParentID +  "</Field>" +

you can do this:

                updateXML += "<Method ID='" + index++ + "' Cmd='New'>" +
                        "<Field Name='Title' Type='String'>" + title  +  "</Field>" +
                        "<Field Name='Entry_x0020_Date' Type='Date'>" + entryDate +  "</Field>" +
                        "<Field Name='Hours' Type='Number'>" + hours +  "</Field>" +
                        "<Field Name='IssueID' Type='Number'>" + newParentID +  "</Field>" +

I know that this may seem nitpicky, but it’s a nice little shorthand and it sometimes helps (at least it helps me) to see where I’m adding to strings versus setting them to a new value.

  • There’s a little typo at the end. Spaces in the middle of the internal names of columns are represented by “_x0020”. Remember your ASCII character codes? Almost any character which isn’t a letter or number will be represented this way, using the hexadecimal ASCII value. Here are a few examples: 
    • ( is _x0028_ and ) is _x0029_
    • The underscore ‘_’ is _x005f_
    • etc.

Thanks, Mark for a great article!

Passing a Source Parameter on the Query String with Multiple Other Parameters

I’ve posted on similar tricks to this in the past, but this little trick is really helpful and worth calling out on its own.  Say that you’d like to pass a Source parameter on the query String, as SharePoint often does for you:


Simple, and you see it all the time as you navigate around in SharePoint. In many cases, you’d also like to pass additional parameters that will “travel along” with the Source parameter.  The trick for this is to simply encode the ampersand (&) character so that it won’t be treated as the start of a new Query String parameter, but instead just a part of the Source parameter. The ASCII value for the ampersand is 26 in hex, so you encode it as %26 in the URL:


Note that I’m passing in the relative URL for the default.aspx page.  Get into the habit of using relative URLs all the time and you’ll be in much better shape in general.

With the above URL, when you are finished with the EditForm.aspx page, whether by clicking OK or Cancel, you’ll be redirected to:


Encoding Query String Values Between .ASPX Pages

I ran into an instance today where a column’s data contained the ampersand (&) character when I hadn’t expected it to.  Since the ampersand is used to separate Query String name/value pairs in the URL, that ampersand was causing me problems.

In general, you should always encode Query String values just in case they might contain a reserved character.  Here’s the code snippet from my page (In another section of my XSL, I pass the selected value on the Query String.):

            <xsl:if test=”@Business_x0020_Group = $Group”>
                <xsl:attribute name=”selected”>true</xsl:attribute>
            <xsl:attribute name=”value”>
                <xsl:value-of select=”ddwrt:UrlEncode(string(@Business_x0020_Group))” />
            <xsl:value-of select=”@Business_x0020_Group” />

As you can see in the bolded line, the ddwrt:UrlEncode function takes care of things for me.  Note that you must do the explicit type conversion to string or you will get an error.  (This is the case with most of the ddwrt namespace functions.)  In the case where I had a Business Group with the string ‘[RR&C]’ in it, the ddwrt:UrlEncode function returned ‘%5bRR%26C%5d’, which can be passed as a Query String value with no issues.