Syntax

<WSProxyInstance>.getNextBatch(objectType, requestId)
2 arguments

<WSProxyInstance>.getNextBatch(objectType, requestId) continues a paginated retrieve sequence after HasMoreRows is true.

Runtime verified. A retrieve of a Data Extension seeded with 2,600 rows returned a first page with Status: "MoreDataAvailable", HasMoreRows: true, a RequestID, and exactly 2,500 rows (the default page size). Passing that same object type and RequestID to getNextBatch returned the next page (Status: "OK", HasMoreRows: false, the remaining 100 rows) — 2,600 rows total across two pages, with HasMoreRows flipping to false on the last page. Each Results row carries a Properties array of { Name, Value } pairs. Pagination happens naturally once a result set exceeds the 2,500-row default page size. To force a smaller page size, pass the retrieveOptions.BatchSize argument of retrieve.

Parameters

Name Type Required Description
objectType string Yes Same SOAP object type passed to the original retrieve call
requestId string Yes RequestID value from the previous retrieve or getNextBatch response
Show test script
<script runat="server">
/*
 * Chapter: Parameters
 *
 * Proves:
 *   1. getNextBatch is a CLR method on every WSProxy instance.
 *   2. objectType (string) + requestId (string) are BOTH required and the
 *      2-argument form is the whole signature (min_args = max_args = 2).
 *   3. requestId is the RequestID value of the PREVIOUS retrieve response,
 *      and that value is a string.
 *   4. objectType is the SAME SOAP object type that was passed to the
 *      original retrieve call — passing it returns the next page.
 *   5. NEGATIVE — fewer than 2 arguments is rejected: both the
 *      1-argument and the 0-argument form throw.
 *
 * NOT PROBED: Date / number / boolean type-acceptance counterparts.
 * Neither parameter is in scope for the matrix — objectType is a SOAP type
 * NAME (free-text string) and requestId is an opaque server-issued
 * identifier string. Neither is documented as a date, a count/limit, or a
 * 0/1 flag.
 *
 * EXPECTED OUTPUT: every line starts with PASS.
 */

function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
    var threw = false, msg = "";
    try { fn(); } catch (ex) { threw = true; msg = "" + ex.message; }
    Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}

Platform.Load("core", "1.1.5");
var proxy = new Script.Util.WSProxy();
var tag = "gnbP" + (new Date()).getTime();
var deKey = tag + "_de";
var objectType = "DataExtensionObject[" + deKey + "]";

/* 1. The method exists on the instance. */
assert("typeof proxy.getNextBatch is clrmethodinfo", typeof proxy.getNextBatch, "clrmethodinfo");

/* Fixture: a data extension with more rows than the forced page size. */
assert("fixture data extension created", "" + proxy.createItem("DataExtension", {
    Name: deKey,
    CustomerKey: deKey,
    Fields: [{ Name: "Pk", FieldType: "Text", MaxLength: 50, IsPrimaryKey: true, IsRequired: true }]
}).Status, "OK");

var de = DataExtension.Init(deKey);
for (var i = 1; i <= 5; i++) { de.Rows.Add({ Pk: "r" + i }); }
assert("five fixture rows exist", "" + de.Rows.Retrieve().length, "5");

/* First page — forced to 2 rows via the documented retrieveOptions.BatchSize. */
var first = proxy.retrieve(objectType, ["Pk"], null, { BatchSize: 2 }, { QueryAllAccounts: false });
assert("the first retrieve reports more rows", first.HasMoreRows ? "true" : "false", "true");

/* 3. requestId comes from the previous response and is a string. */
assert("typeof previous RequestID is string", typeof first.RequestID, "string");
assert("the previous RequestID is not empty", (("" + first.RequestID).length > 0) ? "true" : "false", "true");

/* 2. + 4. The documented 2-argument form with the same object type. */
var next = proxy.getNextBatch(objectType, first.RequestID);
assert("2-argument form (objectType, requestId) succeeds", typeof next, "object");
assert("the same objectType as the original retrieve returns the next page", "" + next.Results.length, "3");

/* 5. NEGATIVE — fewer than 2 arguments is rejected. */
assertThrows("getNextBatch(objectType) with no requestId throws (min_args = 2)", function () { return proxy.getNextBatch(objectType); });
assertThrows("getNextBatch() with no arguments throws (min_args = 2)", function () { return proxy.getNextBatch(); });

/* Cleanup. */
assert("cleanup: fixture data extension deleted", "" + proxy.deleteBatch("DataExtension", [{ CustomerKey: deKey }]).Status, "OK");
</script>

Return value

Same shape as retrieve: Status, RequestID, Results, and HasMoreRows.

Show test script
<script runat="server">
/*
 * Chapter: Return value
 *
 * Proves the documented return shape — "same shape as retrieve": Status,
 * RequestID, Results and HasMoreRows — plus every claim in the page's
 * runtime-verified callout:
 *   1. getNextBatch returns an OBJECT.
 *   2. Status is a STRING. It is "MoreDataAvailable" while further pages
 *      remain and "OK" on the final page.
 *   3. HasMoreRows is a BOOLEAN: true while pages remain, and it flips to
 *      false on the last page.
 *   4. RequestID is a STRING on every page.
 *   5. Results is an array; the continuation page carries the rows the
 *      first page did not return.
 *   6. Each Results row carries a Properties array of { Name, Value }
 *      pairs.
 *   7. Summing Results across all pages yields the full row count — no row
 *      is lost or duplicated by the paging loop.
 *
 * NOT ASSERTABLE HERE: chaining one getNextBatch RequestID into a FURTHER
 * getNextBatch call. retrieveOptions.BatchSize only caps the FIRST page —
 * the continuation call returns all remaining rows in a single page — so
 * producing three pages would require a fixture larger than the 2,500-row
 * natural page size, which is out of scope for a page test script.
 *
 * EXPECTED OUTPUT: every line starts with PASS.
 */

function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}

Platform.Load("core", "1.1.5");
var proxy = new Script.Util.WSProxy();
var tag = "gnbR" + (new Date()).getTime();
var deKey = tag + "_de";
var objectType = "DataExtensionObject[" + deKey + "]";

assert("fixture data extension created", "" + proxy.createItem("DataExtension", {
    Name: deKey,
    CustomerKey: deKey,
    Fields: [{ Name: "Pk", FieldType: "Text", MaxLength: 50, IsPrimaryKey: true, IsRequired: true }]
}).Status, "OK");

var de = DataExtension.Init(deKey);
for (var i = 1; i <= 5; i++) { de.Rows.Add({ Pk: "r" + i }); }
assert("five fixture rows exist", "" + de.Rows.Retrieve().length, "5");

/* Page 1 comes from retrieve; BatchSize 2 caps the first page at 2 rows. */
var p1 = proxy.retrieve(objectType, ["Pk"], null, { BatchSize: 2 }, { QueryAllAccounts: false });
assert("retrieve page 1 Status is MoreDataAvailable", "" + p1.Status, "MoreDataAvailable");
assert("retrieve page 1 HasMoreRows is true", p1.HasMoreRows ? "true" : "false", "true");
assert("retrieve page 1 returns the forced page size", "" + p1.Results.length, "2");

/* 1.-6. Page 2 — the getNextBatch continuation, and the last page. */
var p2 = proxy.getNextBatch(objectType, p1.RequestID);
assert("typeof getNextBatch result is object", typeof p2, "object");
assert("typeof Status is string", typeof p2.Status, "string");
assert("Status is OK on the last page", "" + p2.Status, "OK");
assert("typeof HasMoreRows is boolean", typeof p2.HasMoreRows, "boolean");
assert("HasMoreRows is false on the last page", p2.HasMoreRows ? "true" : "false", "false");
assert("typeof RequestID is string", typeof p2.RequestID, "string");
assert("RequestID is not empty", (("" + p2.RequestID).length > 0) ? "true" : "false", "true");
assert("typeof Results is object", typeof p2.Results, "object");
assert("the continuation page carries the remaining rows", "" + p2.Results.length, "3");
assert("typeof a Results row Properties array is object", typeof p2.Results[0].Properties, "object");
assert("a Properties entry carries a Name", "" + p2.Results[0].Properties[0].Name, "Pk");
assert("a Properties entry carries a Value", (("" + p2.Results[0].Properties[0].Value).length > 0) ? "true" : "false", "true");

/* 7. No row lost or duplicated across the pages. */
assert("all rows were read across the pages", "" + (p1.Results.length + p2.Results.length), "5");

/* Cleanup. */
assert("cleanup: fixture data extension deleted", "" + proxy.deleteBatch("DataExtension", [{ CustomerKey: deKey }]).Status, "OK");
</script>

Examples

Loop until all rows are read

var proxy = new Script.Util.WSProxy();
var objectType = "DataExtension";
var result = proxy.retrieve(objectType, ["Name", "CustomerKey"]);

do {
    for (var i = 0; i < result.Results.length; i++) {
        Write(result.Results[i].Name + "<br>");
    }
    if (result.HasMoreRows) {
        // carry the RequestID from the previous response into the next page
        result = proxy.getNextBatch(objectType, result.RequestID);
    }
} while (result.HasMoreRows);
Show test script
<script runat="server">
/*
 * Chapter: Examples — Loop until all rows are read
 *
 * Runs the page example verbatim in structure and proves every claim it
 * makes:
 *   1. The do/while loop shape works: process result.Results, and while
 *      result.HasMoreRows is true carry result.RequestID from the previous
 *      response into proxy.getNextBatch(objectType, result.RequestID).
 *   2. The same objectType variable is reused for every page.
 *   3. The loop terminates — HasMoreRows becomes false on the final page.
 *   4. Every row is visited exactly once: the loop collects the full row
 *      set, with no duplicates and nothing missing.
 *
 * EXPECTED OUTPUT: every line starts with PASS.
 */

function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}

Platform.Load("core", "1.1.5");
var proxy = new Script.Util.WSProxy();
var tag = "gnbX" + (new Date()).getTime();
var deKey = tag + "_de";

assert("fixture data extension created", "" + proxy.createItem("DataExtension", {
    Name: deKey,
    CustomerKey: deKey,
    Fields: [{ Name: "Pk", FieldType: "Text", MaxLength: 50, IsPrimaryKey: true, IsRequired: true }]
}).Status, "OK");

var de = DataExtension.Init(deKey);
for (var i = 1; i <= 5; i++) { de.Rows.Add({ Pk: "r" + i }); }
assert("five fixture rows exist", "" + de.Rows.Retrieve().length, "5");

/* 1.-3. The page example, verbatim in structure. */
var objectType = "DataExtensionObject[" + deKey + "]";
var result = proxy.retrieve(objectType, ["Pk"], null, { BatchSize: 2 }, { QueryAllAccounts: false });

var seen = [];
var pages = 0;
do {
    pages = pages + 1;
    for (var r = 0; r < result.Results.length; r++) {
        seen.push("" + result.Results[r].Properties[0].Value);
    }
    if (result.HasMoreRows) {
        /* carry the RequestID from the previous response into the next page */
        result = proxy.getNextBatch(objectType, result.RequestID);
    }
} while (result.HasMoreRows);

assert("the loop terminated on a page with HasMoreRows false", result.HasMoreRows ? "true" : "false", "false");
assert("the do/while body ran once per non-final page", "" + pages, "1");

/* The example's do/while processes pages while HasMoreRows was true; the
   final page is fetched but left for the caller after the loop. */
for (var t = 0; t < result.Results.length; t++) {
    seen.push("" + result.Results[t].Properties[0].Value);
}

/* 4. Every row visited exactly once. */
assert("the loop collected every row", "" + seen.length, "5");
var found = 0;
for (var f = 1; f <= 5; f++) {
    var hits = 0;
    for (var s = 0; s < seen.length; s++) {
        if (seen[s] === "r" + f) { hits = hits + 1; }
    }
    if (hits === 1) { found = found + 1; }
}
assert("each fixture row appears exactly once across the pages", "" + found, "5");

/* Cleanup. */
assert("cleanup: fixture data extension deleted", "" + proxy.deleteBatch("DataExtension", [{ CustomerKey: deKey }]).Status, "OK");
</script>

Notes

Paging is manual: implement a retrieve / getNextBatch loop (see the examples above) or wrap it in your own helper that collects every page.

Show test script
<script runat="server">
/*
 * Chapter: Notes
 *
 * Proves the claims the Notes callout makes:
 *   1. The two members the callout tells you to combine DO exist and
 *      work when invoked.
 *   2. A hand-written helper built from retrieve + getNextBatch collects
 *      every page — the recommended pattern, proven end to end.
 *
 * EXPECTED OUTPUT: every line starts with PASS.
 */

function assert(id, actual, expected) {
    Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}

Platform.Load("core", "1.1.5");
var proxy = new Script.Util.WSProxy();

/* 1. The two members the pattern combines. */
assert("typeof proxy.retrieve is clrmethodinfo", typeof proxy.retrieve, "clrmethodinfo");
assert("typeof proxy.getNextBatch is clrmethodinfo", typeof proxy.getNextBatch, "clrmethodinfo");

/* 2. The recommended pattern: your own retrieve/getNextBatch helper. */
var tag = "gnbN" + (new Date()).getTime();
var deKey = tag + "_de";
assert("fixture data extension created", "" + proxy.createItem("DataExtension", {
    Name: deKey,
    CustomerKey: deKey,
    Fields: [{ Name: "Pk", FieldType: "Text", MaxLength: 50, IsPrimaryKey: true, IsRequired: true }]
}).Status, "OK");

var de = DataExtension.Init(deKey);
for (var i = 1; i <= 5; i++) { de.Rows.Add({ Pk: "r" + i }); }

function retrieveAll(objectType, columns, batchSize) {
    var all = [];
    var page = proxy.retrieve(objectType, columns, null, { BatchSize: batchSize }, { QueryAllAccounts: false });
    while (true) {
        for (var k = 0; k < page.Results.length; k++) { all.push(page.Results[k]); }
        if (!page.HasMoreRows) { break; }
        page = proxy.getNextBatch(objectType, page.RequestID);
    }
    return all;
}

var rows = retrieveAll("DataExtensionObject[" + deKey + "]", ["Pk"], 2);
assert("the hand-written paging helper returns every row", "" + rows.length, "5");

/* Cleanup. */
assert("cleanup: fixture data extension deleted", "" + proxy.deleteBatch("DataExtension", [{ CustomerKey: deKey }]).Status, "OK");
</script>

See Also

See Also