Sample code to retrieve more than 5000 records using FetchXML in CRM

Hi,

Sharing a sample code to retrieve more than 5000 records using the Fetch XML.

Version 1 :


private List<Entity> GetTotalRecordsfromFetch(string fetchXML, IOrganizationService orgService)
{
List<Entity> lstEntity = new List<Entity>();

int fetchCount = 5000;
int pageNumber = 1;
string pagingCookie = null;

while (true)
{
// Build fetchXml string with the placeholders.
string xml = this.CreateXml(fetchXML, pagingCookie, pageNumber, fetchCount);
RetrieveMultipleRequest fetchRequest = new RetrieveMultipleRequest
{
Query = new FetchExpression(xml)
};

var returnCollections = ((RetrieveMultipleResponse)orgService.Execute(fetchRequest)).EntityCollection;

if (returnCollections.Entities.Count >= 1)
{
lstEntity.AddRange(returnCollections.Entities);
}

if (returnCollections.MoreRecords)
{
pageNumber++;

results.pagingCookie = returnCollections.PagingCookie;
}
else
{
// If no more records in the result nodes, exit the loop.
break;
}
}

return lstEntity;
}

public string CreateXml(string xml, string cookie, int page, int count)
{
StringReader stringReader = new StringReader(xml);
XmlTextReader reader = new XmlTextReader(stringReader);

XmlDocument doc = new XmlDocument();
doc.Load(reader);

XmlAttributeCollection attrs = doc.DocumentElement.Attributes;

if (cookie != null)
{
XmlAttribute pagingAttr = doc.CreateAttribute("paging-cookie");
pagingAttr.Value = cookie;
attrs.Append(pagingAttr);
}

XmlAttribute pageAttr = doc.CreateAttribute("page");
pageAttr.Value = System.Convert.ToString(page);
attrs.Append(pageAttr);

XmlAttribute countAttr = doc.CreateAttribute("count");
countAttr.Value = System.Convert.ToString(count);
attrs.Append(countAttr);

StringBuilder sb = new StringBuilder(1024);
StringWriter stringWriter = new StringWriter(sb);

XmlTextWriter writer = new XmlTextWriter(stringWriter);
doc.WriteTo(writer);
writer.Close();

return sb.ToString();
}

Version 2 :


private static List<Entity> GetTotalRecordsFetchXML(OrganizationServiceProxy orgProxy, string fetchXML)
{
XDocument xDocument = XDocument.Parse(fetchXML);
var fetchXmlEntity = xDocument.Root.Element("entity").ToString();

EntityCollection entityColl = new EntityCollection();
List<Entity> lstEntity = new List<Entity>();
int page = 1;
do
{

entityColl = orgProxy.RetrieveMultiple(new FetchExpression(
string.Format("<fetch version='1.0' page='{1}' paging-cookie='{0}'>" + fetchXmlEntity + "</fetch>",
SecurityElement.Escape(entityColl.PagingCookie), page++)));

lstEntity.AddRange(entityColl.Entities);
}
while (entityColl.MoreRecords);

return lstEntity;
}

Hope it helps..

Missing RemoveListMembersListRequest in CRM.

In one of our recent implementations, we were working with Marketing List which could be in millions.

So we had the recent request wherein we split the marketing list into groups.

For adding members to a marketing list we have the following request

AddListMembersListRequest 

https://msdn.microsoft.com/en-us/library/microsoft.crm.sdk.messages.addlistmemberslistrequest.aspx

which is quite efficient as we can add multiple members in a single request.

However, when it comes to removing a member from marketing, we do not have a corresponding Remove request like RemoveListMembersListRequest.

https://msdn.microsoft.com/en-us/library/microsoft.crm.sdk.messages.removememberlistrequest.aspx

We only have RemoveMemberListRequest, which only removes 1 member at a time, which is highly inefficient when we are taking in consideration large number of records.

Kindly vote up for this idea !!

https://ideas.dynamics.com/ideas/dynamics-crm/ID0002529

More details

https://social.microsoft.com/Forums/en-US/5d700a43-0c57-4a47-9c8e-192c70d30a2d/removememberlistrequest-causes-sql-timeout-error?forum=crmdevelopment

Using Shared Mailbox and Queue in CRM for implementing generic email address in Dynamics 365 and Exchange Online.

Recently, we had a requirement to send email to customers using a generic email address like donotreply@domain.com from Dynamics CRM (& Exchange Online).

The way we can implement this is through Shared Mailbox and Queue in CRM Online.

Log in to the Administration Portal

https://portal.office.com/adminportal/home#/homepage

Select Shared mailboxes

Members can be added to the Shared Mailbox

Now back in CRM assign the email id to a particular queue.

Now sending an email activity with From as Queue and to as one of the user inside CRM.

Open the user’s mail box.

Make sure we have done Test and Enabled Mailbox for the Shared Email Box and have set Incoming and Outgoing Email as Server-Side Synchronization.

Hope it helps..

System.Security.SecurityException: That assembly does not allow partially trusted callers while using HttpUtility.UrlEncode in CRM

Hi,

We got the below error in one of our Sandboxed Plugins

“System.Security.SecurityException: That assembly does not allow partially trusted callers”.

We realised it was because of using System.Web.HttpUtility class


We replaced it with EscapeDataString method and this fixed the issue.

System.Uri.EscapeDataString()

Helpful thread

https://stackoverflow.com/questions/3840762/how-do-you-urlencode-without-using-system-web

Hope it helps..

LINQ: GroupBy, Sum and EntityCollection in CRM

Just sharing a sample code that could be used for group by and sum operation on EntityCollection.

Suppose below is the output that we want

We can use the below code for that.


// select categoryid, final forecast, final awards from SubCategory Entity
// category id is lookup in SubCategory Entity

EntityCollection result = orgProxy.RetrieveMultiple(new FetchExpression(fetch));

var details = from r in result.Entities.AsEnumerable()
group r by new
{
groupByCategoryID = ((EntityReference)r.Attributes["categoryId"]).Id.ToString()
}
into g
select new
{
sumFinalForecast = g.Sum(x => Convert.ToInt32(x.Attributes["finalforecast"])),
sumFinalAwards = g.Sum(x => Convert.ToInt32(x.Attributes["finalawards"])),
categoryId = g.Key.groupByCategoryID
};

// update the parent record
foreach(var detail in details)
{
Entity entityUpdate = new Entity("category");
entityUpdate.Id = new Guid(detail.categoryId);
entityUpdate.Attributes["totalfinalforecast"] = detail.sumFinalForecast;
entityUpdate.Attributes["totalfinalawards"] = detail.sumFinalAwards;
orgProxy.Update(entityUpdate);
}

Hope it helps..

Missing Action (message) in Plugin Registration Tool

Recently we created a new created Action and it twas not showing up in Plugin Registration Tool.

Closing and restarting the Plugin Registration tool fixed it.

Hope it helps..