I am building a fetch XML string including a paging cookie, completing an update on the records on the page and moving on to the next.
I build the fetch with the following: Fetch
string fetchquery1 = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false' count='1' page ='";
string fetchquery2 = @"' paging-cookie='";
string fetchquery3= @"'> <entity name='contact'>
<attribute name='fullname' />
<attribute name='donotbulkemail' />
<order attribute='fullname' descending='false' />
<filter type='and'>
<condition attribute='donotbulkemail' operator='eq' value='0' />
</filter>
</entity>
</fetch>";
string pagingcookie = "";
int page = 0;
Then at the start of the while loop I increment the page and build the fetch:
while (true) {
//increment the page
page++;
//set the fetch
string updatedfetchquery = string.Format(fetchquery1 + page + fetchquery2 + pagingcookie + fetchquery3);
After the first result is returned I grab the cookie and I clean it's format
pagingcookie = accounts.PagingCookie;
if (pagingcookie.Contains("<"))
{
pagingcookie = pagingcookie.Replace("<", "<");
pagingcookie = pagingcookie.Replace("\"", """);
pagingcookie = pagingcookie.Replace(">", ">");
}
A console.write
shows me I have the correct format for the cookie which is added within the string
<cookie page="1"><fullname last="=Vena Winton" first="=Vena Winton" /><contactid last="{0BB28D30-BD77-E711-810B-E0071B66F061}" first="{0BB28D30-BD77-E711-810B-E0071B66F061}" /></cookie>
What I find is that the first page is executed succesfully, the second page fails with the following:
System.FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
on the line where the fetch xml string is built.
If I remove the paging cookie reference in the fetch string then the code will continue to execute happily until Microsoft Dynamics decides I've had enough pages without using a paging cookie.
Here's the full code:
string fetchquery1 = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false' count='1' page ='";
string fetchquery2 = @"' paging-cookie='";
string fetchquery3= @"'> <entity name='contact'>
<attribute name='fullname' />
<attribute name='donotbulkemail' />
<order attribute='fullname' descending='false' />
<filter type='and'>
<condition attribute='donotbulkemail' operator='eq' value='0' />
</filter>
</entity>
</fetch>";
string pagingcookie = "";
int page = 0;
while (true) {
//increment the page
page++;
//set the fetch
string updatedfetchquery = string.Format(fetchquery1 + page + fetchquery2 + pagingcookie + fetchquery3);
Console.WriteLine(page);
{
var multipleRequest = new Microsoft.Xrm.Sdk.Messages.ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
Console.WriteLine(updatedfetchquery);
EntityCollection accounts = service.RetrieveMultiple(new FetchExpression(updatedfetchquery));
foreach (var c in accounts.Entities)
{
Microsoft.Xrm.Sdk.Messages.UpdateRequest updateRequest = new Microsoft.Xrm.Sdk.Messages.UpdateRequest { Target = c };
multipleRequest.Requests.Add(updateRequest);
c.Attributes["donotbulkemail"] = true;
//Console.WriteLine("accountid: {0}", c.Attributes["donotbulkemail"]);
Console.WriteLine(updatedfetchquery);
// Console.WriteLine(page);
pagingcookie = accounts.PagingCookie;
if (pagingcookie.Contains("<"))
{
pagingcookie = pagingcookie.Replace("<", "<");
pagingcookie = pagingcookie.Replace("\"", """);
pagingcookie = pagingcookie.Replace(">", ">");
}
}
Microsoft.Xrm.Sdk.Messages.ExecuteMultipleResponse multipleResponse = (Microsoft.Xrm.Sdk.Messages.ExecuteMultipleResponse)service.Execute(multipleRequest);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
}
}
We have a GetAll helper method defined which handles all of the paging cookie complexity for you
public static List<Entity> GetAll(IOrganizationService service, QueryExpression query)
{
var entities = new List<Entity>();
query.PageInfo = new PagingInfo();
query.PageInfo.Count = 5000;
query.PageInfo.PagingCookie = null;
query.PageInfo.PageNumber = 1;
var res = service.RetrieveMultiple(query);
entities.AddRange(res.Entities);
while (res.MoreRecords == true)
{
query.PageInfo.PageNumber++;
query.PageInfo.PagingCookie = res.PagingCookie;
res = service.RetrieveMultiple(query);
entities.AddRange(res.Entities);
}
return entities;
}
Although this is designed to work with QueryExpressions, you can easily convert your FetchXML query to a query expression using the SDK FetchXmlToQueryExpressionRequest method.