Getting Around SharePoint’s Threshold Limits for Large Reference Lists

In SharePoint 2007, we could build lists that contained as many items as we wanted and access them in any way we wanted. We may have done stupid things that were bad for server performance, but if we knew what we were doing there were few limits. We had the mythical “2000 item” rule of thumb (which had little basis in reality in many, many cases) but otherwise it was up to us. (See: Plan for software boundaries (Office SharePoint Server))

In SharePoint 2010, Microsoft introduced threshold limits to protect us from ourselves. This seemed counter intuitive to me, since with the upgrade to SharePoint 2010, one also had to go to 64 bit architecture and put a heck of a lot more iron behind the SharePoint farm. While we could potentially store 30,000,000 items in a list (30 million!), we had a list view threshold of 5000 items. (See: SharePoint Server 2010 capacity management: Software boundaries and limits)

SharePoint 2013 maintains similar limits to 2010, with 5000 items the limit for a list view. (See: Software boundaries and limits for SharePoint 2013)

List View ThrottlingSomehow, as technology has moved forward – significantly – we’ve got more limits.

5000 items is way too many to ever show in a list view, but it may not be if you want to do some client side processing. It doesn’t matter if you’re trying to build a truly bloated, Bad Idea list view or request data using REST, you’re stuck with that 5000 item limit.

But what if you know what you are doing and the 5000 item limit doesn’t work for you? I’ve written in the past about why we shouldn’t change some of the threshold limits (e.g.,  The SharePoint 2010 “List View Lookup Threshold” and Why We Don’t Change It).

If we’re working on Office365, we simply can’t change the limits – Microsoft gets to decide what they are. Sometimes those limits change without notice, too, so it’s truly out of our hands.

Well, what does all this add up to? Let’s take a specific example.

I needed to provide auto complete functionality in an InfoPath form. It was the classic scenario: we had a list of [in this case] 19,000+ cities and towns and we needed a good UX for entering selections into the form. We run into this sort of thing with data like cities and towns all the time. There are too many choices for a dropdown to make any sense, and SharePoint doesn’t offer up any better alternatives. jQueryUI’s autocomplete function is a perfect solution for this sort of thing.

The data was in a spreadsheet, and it’s easy to upload data from a spreadsheet to a SharePoint list. Bingo, bango, done, right? Well, no. It’s impossible to upload data from a spreadsheet *and* index the column. We need to index the column so that we can make type of requests requests that we need for autocomplete – basically, give me all of the items that begin with or contain this string – or else we run into the 5000 item threshold error on our requests.

No problem! We’ll just upload the data and *then* index the column. Not so fast, mister. When you try to index the column you run into – you guessed it – the 5000 item limit. No indexee, no laundry.

So seemingly we’re stuck. But wait – we can just create the list in the UI, add the index, and paste all 19,000 items into the Brave New World of SharePoint 2013′s “data sheet view” aka “Quick Edit”. Sadly, when I tried to paste in more than a few hundred items, the browser hung on me. This was on Office365, and I tried several different browsers. SharePoint Online seems to prefer nibbles to big bites of data. Unless I spent days just doing the pasting, this was never going to happen.

In this case, I decided to simply store the data in a txt file containing JSON rather than trying to force it into a list. Thanks to @bpmccullough for the suggestion on Twitter.

The data I orignially has received for the sities and towns was in a CSV file. I found a nice little site that would convert the CSV format to JSON (bookmark this one; you’ll need it in this JSON-oriented world).

Once I had the JSON file uploaded to a Document Library, the code below is what I used to set up the autocomplete. We wanted the autocomplete to allow multiple choices, so there’s a little monkeying around to enable that. It wasn’t tremendously peppy (19,000 cities, after all), but it worked. Remember, kids: this is an example. Don’t expect to drop it into your page and have it work.

var citiesAndStates = [];

// Get the City and State data from the file with JSON data
$.getJSON("/Shared%20Documents/CityState.txt", function(data) {
  var results = $(data);
  // Push the data into an array which is appropriate for jQueryUI autocomplete
  citiesAndStates = ($.map(results, function(item) {
    return {
      label: item.State + " - " + item.City, // Show "State - City" [e.g., MA - Boston] for selection
      value: item.City + ", " + item.State // Show "City, State" [e.g., Boston, MA] upon selection
    }
  }));
});

// When the field is available and gets focus, set up the autocomplete behavior
//ctl00_ctl42_g_6069846d_1b7f_4890_b767_2bdc15d2b133_FormControl0_V1_I1_S15_I4_T5
$(document).on("focus", "input[id$='FormControl0_V1_I1_S15_I4_T5']", function() {
  if ($(this).data("autocompleteSet") === undefined) {
    $(this).data("autocompleteSet", true);

    $(this)
    // Don't navigate away from the field on tab when selecting an item
    .bind("keydown", function(event) {
      if (event.keyCode === $.ui.keyCode.TAB && $(this).data("ui-autocomplete").menu.active) {
        event.preventDefault();
      }
    }).autocomplete({
      source: function(request, response) {
        // Delegate back to autocomplete, but extract the last term
        response($.ui.autocomplete.filter(citiesAndStates, extractLast(request.term)));
      },
      minLength: 3,
      focus: function() {
        // Prevent value inserted on focus
        return false;
      },
      select: function(event, ui) {
        var terms = split(this.value);
        // Remove the current input
        terms.pop();
        // Add the selected item
        terms.push(ui.item.value);
        // Add placeholder to get the semicolon-and-space at the end
        terms.push("");
        this.value = terms.join("; ");
        return false;
      }
    });
  }
});

function split(val) {
  return val.split(/;\s*/);
}

function extractLast(term) {
  return split(term).pop();
}

One note here: This approach basically violates my “put all data into a list so that end users can maintain it” rule. However, the approach I came up with was the best one for the situation. It’s still possible for a reasonably savvy (meaning “non-developer”) user to manage the data by downloading the file and using a JSON-aware editor.

The main thing was that we were able to set up something that worked, regardless what the Office365 limits my change to.

Testing Web Applications Using Spoon.Net’s Magic Browser Page

Spoon.netFor quite a while now (my annual subscription is up for renewal soon), I’ve been using Spoon.net‘s virtualized browsers. I’ve tweeted about Spoon.net’s
magic browser page” many times, but I think it’s post-worthy.

Spoon.net Free Virtualized Browsers

Spoon.net Free Virtualized Browsers

Not only are the virtualized browsers great for testing sites, they also really come in handy when I need to access a client VPN or system using a down-level version. IE8 may not be the darling of designers anywhere, but it sure is the darling of many enterprise IT departments.

Now that I’m running Windows 8.1 on my laptop, with IE11 coming along for the ride, I’m using the Spoon.net virtualized browsers more and more. I still do a lot of work with SharePoint 2007 and 2010, and IE11 just doesn’t cut it. Heck, IE11 still doesn’t cut it with SharePoint 2013!

But I digress. With the plethora of browser versions available at Spoon.net, you can test just about anything. Or, if you’re like me and need different browser versions all the time just to work, it’s very worth the subscription price. (The Spoon.net pricing is quite reasonable, considering all you get.)

 Legacy Browsers Requires upgrade

Legacy Browsers
Requires upgrade

When I was thinking about writing this post, I reached out to Colin McIntosh, who is one of the business development guys at Spoon.net, to see what else I should know. I’m taking advantage of very little of what Spoon.net gives me, and I knew that was the case. I didn’t realize how much else was there, some of it covered by my subscription.

Disclaimer: There is no disclaimer. As of this writing, I’ve received no compensation or free services from Spoon.net. Everything I’ve said above is based on my satisfaction with the Spoon.net services. I highly recommend them.

Here’s what Colin let me know about their other services, some of which are upcoming. As you can see, there’s a LOT more. I’m actually surprised that more people don’t know about them.

Main enterprise products

Spoon Studio

Our app virtualization engine. Studio allows businesses to virtualize their entire software infrastructure, including run-times and other dependencies.

Spoon Server

An on-premise version of Spoon.net that allows IT administrators to centrally deploy and manage applications and data to end users anywhere in the world.

Here are a couple topical use cases:
Run legacy XP apps on Windows 7 and 8 – Spoon Studio packages applications and their runtimes into a virtual application, a standalone executable that can run on any Windows OS. This enables past and present versions of the same app to run simultaneously on the same machine.

Run Java applications without Java on the host machine – Java security holes are a huge issue right now for companies and consumers who don’t want themselves exposed to Java-based exploits. Because Spoon virtualizes runtimes along with their applications, virtual apps run in a virtual environment (the Spoon VM) that’s isolated from the host system. Packaging Java together with the app removes the need to install Java on the host desktop, which mitigates the risk of malicious attacks from Java-based exploits.

Some new products due to release soon

URL Redirect (catchier name in the works)

Basically, Spoon applications will automatically open links in the correct version of the correct browser, no matter the default browser on the host desktop (or the one that an employee may be incorrectly trying to use).

Browser redirection is a service that automatically opens the page or resource a user is trying to visit in an alternate browser. It uses a browser plugin to check URLs against a predetermined list of rules that specify which websites are incompatible with the user’s current browser. If the URL matches a rule, the webpage will launch in the specified virtual browser instead of their native browser. If the URL does not match any of the rules then it will load in the user’s native browser as usual.

Browser redirection prevents errors when accessing legacy web resources on newer systems, creating a more seamless and efficient web experience for the end user.

Browser Studio

This is going to be a standalone web app that lets any user create their own custom virtual browser. You would go to browserstudio.com, pick a “base” browser (IE, Chrome, Firefox, etc.) at any version level, pick any additional run-times you want to add to your browser (Java, .NET. Flash, etc.), and then configure browser settings any way you like. Then you can configure network settings, add plugins, etc., and finally name it yourself and give it a custom icon! You could then publish it to your spoon.net account, share it with your spoon.net team, publish it in a private web server (like Spoon Server), or install it on your own desktop.

Spoon is also fantastic for BYOD, and we’re coming out with mobile and Mac versions in the very near future. We’re excited for what lies ahead, and because we’re completely employee-owned, we’re one of the few companies that can act completely independently (no VC here).

Regex Selector for jQuery by James Padolsey FTW

In researching how to fix the issue with Office 365 Update Changes ‘Display Name’ on Required Fields in SPServices, I came across some true awesomeness from James Padolsky (@).

jQuery is eminently extendable, and people do it all the time by creating plugins, additional libraries, etc. After all, it’s all just JavaScript, right? However, I’ve never seen such a nicely packaged selector extension as what James has done with his :regex extension.

In his Regex Selector for jQuery, James has given us exactly what we need to get around this nasty ” Required Field” thing.

jQuery.expr[':'].regex = function(elem, index, match) {
  var matchParams = match[3].split(','),
    validLabels = /^(data|css):/,
    attr = {
      method: matchParams[0].match(validLabels) ?
        matchParams[0].split(':')[0] : 'attr',
        property: matchParams.shift().replace(validLabels,'')
    },
    regexFlags = 'ig',
    regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
  return regex.test(jQuery(elem)[attr.method](attr.property));
}

By adding this nice little chunk of JavaScript into SPServices, I get a nice, clean way to implement a fix. In the snippet of code below from the DropDownCtl function in SPServices, I can maintain backward compatibility (all the way back to SharePoint 2007 – WSS 3.0, even)

// Simple, where the select's title attribute is colName (DisplayName)
//  Examples:
//      SP2013 <select title="Country" id="Country_d578ed64-2fa7-4c1e-8b41-9cc1d524fc28_$LookupField">
//      SP2010: <SELECT name=ctl00$m$g_d10479d7_6965_4da0_b162_510bbbc58a7f$ctl00$ctl05$ctl01$ctl00$ctl00$ctl04$ctl00$Lookup title=Country id=ctl00_m_g_d10479d7_6965_4da0_b162_510bbbc58a7f_ctl00_ctl05_ctl01_ctl00_ctl00_ctl04_ctl00_Lookup>
//      SP2007: <select name="ctl00$m$g_e845e690_00da_428f_afbd_fbe804787763$ctl00$ctl04$ctl04$ctl00$ctl00$ctl04$ctl00$Lookup" Title="Country" id="ctl00_m_g_e845e690_00da_428f_afbd_fbe804787763_ctl00_ctl04_ctl04_ctl00_ctl00_ctl04_ctl00_Lookup">
if ((this.Obj = $("select[Title='" + colName + "']")).length === 1) {
  this.Type = "S";
// Simple, where the select's id begins with colStaticName (StaticName) - needed for required columns where title="colName Required Field"
//   Examples:
//      SP2013 <select title="Region Required Field" id="Region_59566f6f-1c3b-4efb-9b7b-6dbc35fe3b0a_$LookupField" showrelatedselected="3">
} else if ((this.Obj = $("select:regex(id, (" + colStaticName + ")(_)[0-9a-fA-F]{8}(-))")).length === 1) {
  this.Type = "S";

The regex I need to use isn’t too complicated, and the best part is that I can use it right in a jQuery selector with the :regex extension. Here I’m looking for an id which starts with the column’s StaticName followed by an underscore (_) and then 8 hexadecimal characters [0-9a-fA-F] and then a dash (-). That ensures that I’m finding the right id without the greedy selection issues on the title I may run into using some of the other methods people have suggested.

This fix is in the latest alpha of 2014.01, which is named 2014.01ALPHA2. I think that this will be the winning fix, and I’ve already gotten some positive feedback from folks who have tested it. If you have the issue and could test as well, I’d appreciate it. Because the DropDownCtl is the one function I use to find dropdowns for all of the other SPServices function, this should fix all of them.

Now, if we could just get the SharePoint Product Group to stop messing with our markup!

SPServices Stories #20 – Modify User Profile Properties on SharePoint Online 2013 using SPServices

Introduction

Sometimes people ask me why I’m still bothering with the crufty old SOAP Web Services in SPServices. After all, there are REST and CSOM to play with and Microsoft has decided to deprecate the SOAP Web Services.

Well in some cases, the Shiny New Toys don’t let you get the job done. In cases where you’re implementing on Office365 and simply can’t deploy server side code, SPServices can sometimes be just the right tool. It’s easy to use and it gets stuff done that you need. What more can I say?

I found this nice story from Gary Arora about updating User Profile data a few weeks back. In it, Gary shows us how to easily make those updates on Office365 using SPServices. Gary calls himself “your friendly neighborhood SharePointMan” and he is happy to be have his story be one of my stories.

The Use Case

SharePoint 2013 users need to modify (specific) user-profile-properties client-side without having to navigate away to their ‘MySite’ site and swift through rows of user properties.
(Following is an mock-up showing a simple interface to update a user profile property via CEWP)

Modify_User_Profile_Properties_SharePoint

Simple interface to update Fax number from a CEWP. (Basic demo)

The Usual Solution

In the SharePoint 2013 universe there are 2 ways to read/write data client-side. CSOM and REST. Unfortunately CSOM and REST are not fully there yet when it comes to matching the server side functionality.

In this specific case, one could use CSOM or REST to retrieve (read) User Profile Properties but there is no way to modify (update) these properties from client-side. Here’s Microsoft’s official position.

Not all functionality that you find in the Microsoft.Office.Server.UserProfiles assembly is available from client APIs. For example, you have to use the server object model to create or change user profiles because they’re read-only from client APIs (except the user profile picture)

Hence The Dirty Workaround

So our workaround is SOAP, the forgotten granddaddy of Web services. The User Profile Service web service, from the SharePoint 2007 days, has a method called ModifyUserPropertyByAccountName which functions exactly as it sounds. But since SOAP can be a bit intimidating & ugly to write, we’ll use SPServices, ”a jQuery library which abstracts SharePoint’s Web Services and makes them easier to use”

So here’s how we’ll use SPServices to modify User Profile Properties. The method is applicable to SharePoint 2013 & 2010 (online & on-prem) versions.

1. Reference SPServices library

You have two options here. You can either download the SPService library and reference it locally or reference it from its CDN:

<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2013.01/jquery.SPServices-2013.01.min.js"></script>

2. Create updateUserProfile() Function

The following function simulates the ModifyUserPropertyByAccountName method on the User Profile Service web service.

function updateUserProfile(userId, propertyName, propertyValue) {

  var propertyData = "<PropertyData>" +
  "<IsPrivacyChanged>false</IsPrivacyChanged>" +
  "<IsValueChanged>true</IsValueChanged>" +
  "<Name>" + propertyName + "</Name>" +
  "<Privacy>NotSet</Privacy>" +
  "<Values><ValueData><Value xsi:type=\"xsd:string\">" + propertyValue + "</Value></ValueData></Values>" +
  "</PropertyData>";
  
  $().SPServices({
    operation: "ModifyUserPropertyByAccountName",
    async: false,
    webURL: "/",
    accountName: userId,
    newData: propertyData,
    completefunc: function (xData, Status) {
      var result = $(xData.responseXML);
    }
  });

}

3. Invoke updateUserProfile() Function

This function takes 3 parameters.

  • userId: Your userID. The format is “domain\userId” for on-prem and “i:0#.f|membership|<federated ID>” for SharePoint Online.
  • propertyName: The user profile property that needs to be changed
  • propertyValue: The new user profile property value

Example:

updateUserProfile(
  "i:0#.f|membership|garya@aroragary.onmicrosoft.com",
  "Fax", "555 555 5555");

Note: The above code works but notice that you are passing a hardcoded userId.

To pass the current userId dynamically, we can use CSOM’s get_currentUser(). But since that’s based on the successful execution of ClientContext query, we need to “defer” invoking “updateUserProfile()” until we have received current userId. Therefore we’ll create a Deferred object as follows:

function getUserLogin() {
  var userLogin = $.Deferred(function () {
    var clientContext = new SP.ClientContext.get_current();
    var user = clientContext.get_web().get_currentUser();
    clientContext.load(user);
    clientContext.executeQueryAsync(
      function () {
        userLogin.resolve(user.get_loginName());
      }
      ,
      function () {
        userLogin.reject(args.get_message());
      }
      );
  });
  return userLogin.promise();
}

Now when we invoke updateUserProfile(), it will execute getUserLogin() first, implying that the ClientContext query was successful :

getUserLogin().done(function (userId) {
  updateUserProfile(userId, "Fax", "555 555 5555");
});

4. Full working code

Steps to replicate the demo

  1. Copy the following code snippet and save it as a text file (.txt)
  2. Upload this text file anywhere on your SharePoint site (e.g. Site Assets). Remember its path.
  3. On the same SharePoint site, add/edit a page and insert a CEWP (Content Editor Web Part)
  4. On the web part properties of CEWP, add the path to the text file under “Content Link” section
  5. Click Ok, and save the page.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/2013.01/jquery.SPServices-2013.01.min.js"></script>
<script type="text/javascript">

//updateUserProfilePreFlight defers until getUserId() is "done"
//then it invokes updateUserProfile
function updateUserProfilePreFlight(){
  getUserId().done(function (userId) {
    var propertyName = "Fax"
    var propertyValue =  $("#Fax").val();
    updateUserProfile(userId, propertyName, propertyValue);
  });
}

//getUserLogin() uses CSOM to retrive current userId.
function getUserId() {
  var userLogin = $.Deferred(function () {
    var clientContext = new SP.ClientContext.get_current();
    var user = clientContext.get_web().get_currentUser();
    clientContext.load(user);
    clientContext.executeQueryAsync(
      function () {
        userLogin.resolve(user.get_loginName());
      }
      ,
      function () {
        userLogin.reject(args.get_message());
      }
      );
  });
  return userLogin.promise();
}

//updateUserProfile updates the userprofile property 
function updateUserProfile(userId, propertyName, propertyValue) {

  var propertyData = "<PropertyData>" +
  "<IsPrivacyChanged>false</IsPrivacyChanged>" +
  "<IsValueChanged>true</IsValueChanged>" +
  "<Name>" + propertyName + "</Name>" +
  "<Privacy>NotSet</Privacy>" +
  "<Values><ValueData><Value xsi:type=\"xsd:string\">" + propertyValue + "</Value></ValueData></Values>" +
  "</PropertyData>";

  $().SPServices({
    operation: "ModifyUserPropertyByAccountName",
    async: false,
    webURL: "/",
    accountName: userId,
    newData: propertyData,
    completefunc: function (xData, Status) {
      var result = $(xData.responseXML);
    }
  });

}


</script>

<input id="Fax" type="text" placeholder="Update Fax" />
<input onclick="updateUserProfilePreFlight()" type="button" value="Update" />

Note

  • You can only edit the user profile properties that are editable (unlocked) on your MySite. Certain fields like department are usually locked for editing as per company policy

Finding a Task’s Status Using GetListItems and SPServices in SharePoint 2013

I get interesting questions all this time. This one came from a client who was trying to use GetListItems with SPServices in SharePoint .

Hey Marc, I’m trying to do a GetListItems operation on tasks list and I’m having trouble with the “Task Status” column. This is SP2013.

var thisTaskStatus = $.trim($(this).attr("Status"));
var thisTaskStatus = $.trim($(this).attr("ows_Status"));
var thisTaskStatus = $.trim($(this).attr("ows_Task_x0020_Status"));

None of the above work and I went into the edit column settings of the task list and clicked on the status column and it says the field name is “Status”. When I look at the XML returned using Firebug, a lot of other fields show up like Title, Due Date, Created By, etc. but I don’t see the status column showing up at all in the responseXML.

Many of the out of the box columns have rather obscure StaticNames. In a Tasks list, the column which has the “Status” DisplayName has a StaticName of “Status” as well, so that’s pretty simple. Here’s the field definition, which I grabbed by calling GetList on my own Tasks list:

<Field Type="Choice" ID="{c15b34c3-ce7d-490a-b133-3f4de8801b76}" Name="Status" DisplayName="Task Status" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="Status" ColName="nvarchar4">
  <CHOICES>
   <CHOICE>Not Started</CHOICE>
   <CHOICE>In Progress</CHOICE>
   <CHOICE>Completed</CHOICE>
   <CHOICE>Deferred</CHOICE>
   <CHOICE>Waiting on someone else</CHOICE>
  </CHOICES>
  <MAPPINGS>
    <MAPPING Value="1">Not Started</MAPPING>
    <MAPPING Value="2">In Progress</MAPPING>
    <MAPPING Value="3">Completed</MAPPING>
    <MAPPING Value="4">Deferred</MAPPING>
    <MAPPING Value="5">Waiting on someone else</MAPPING>
  </MAPPINGS>
  <Default>Not Started</Default>
</Field>

Calling GetList to take a look at the list schema is a good way to keep yourself from going crazy.

Now that said, you don’t always get all of the columns for a list when you call GetListItems. By default, you get the columns which are shown in the default view.

In an out of the box Tasks list that I just created, when I make this call:

$().SPServices({
  operation: "GetListItems",
    listName: "Tasks"
});

Status isn’t returned because it’s not in the default view.

<z:row
  ows_Checkmark="boolean;#0"
  ows_LinkTitle="boo"
  ows_AssignedTo=""
  ows_PercentComplete="0.500000000000000"
  ows__ModerationStatus="0"
  ows__Level="1"
  ows_Title="boo"
  ows_ID="1"
  ows_UniqueId="1;#{CC125F6A-F329-46D7-8140-F9353F1AC7EC}"
  ows_owshiddenversion="1"
  ows_FSObjType="1;#0"
  ows_Created_x0020_Date="1;#2014-01-29 13:04:43"
  ows_Created="2014-01-29 13:04:43"
  ows_FileLeafRef="1;#1_.000"
  ows_PermMask="0x7fffffffffffffff"
  ows_Modified="2014-01-29 13:04:43"
  ows_FileRef="1;#sites/Demos2013/jquerylib/Lists/Tasks/1_.000">
</z:row>

Instead, you can add the CAMLViewFields option to request it:

$().SPServices({
  operation: "GetListItems",
    listName: "Tasks",
    CAMLViewFields: "<ViewFields><FieldRef Name='Status'/></ViewFields>"
});

Then I get:

<z:row
  ows_Status="Deferred" 
  ows_MetaInfo="1;#" 
  ows__ModerationStatus="0" 
  ows__Level="1"
  ows_Title="boo" 
  ows_ID="1" 
  ows_UniqueId="1;#{CC125F6A-F329-46D7-8140-F9353F1AC7EC}" 
  ows_owshiddenversion="2" 
  ows_FSObjType="1;#0" 
  ows_Created="2014-01-29 13:04:43" 
  ows_PermMask="0x7fffffffffffffff" 
  ows_Modified="2014-01-29 13:11:21" 
  ows_FileRef="1;#sites/Demos2013/jquerylib/Lists/Tasks/1_.000">
</z:row>

Being explicit about the columns you want to retrieve is always a good practice. People can change the default view easily.