Asked by:
Free Record Counter

General discussion
-
While i was reading this thread i was thinking - is it hard to write such functionality for me or not. I tried and in some hours i retrieved the result. Code which execute required functionality:
using System; using System.Collections.Generic; using System.Text; using Microsoft.Crm.Sdk; using Microsoft.Crm.SdkTypeProxy; using Microsoft.Win32; using System.Xml; using Microsoft.Crm.SdkTypeProxy.Metadata; using Microsoft.Crm.Sdk.Metadata; namespace TestPlugin { public class ExecuteHandler : IPlugin { public ExecuteHandler(string config, string secureConfig) { } #region IPlugin Members public void Execute(IPluginExecutionContext context) { if (context.Depth != 1) //To calculate count of pages and records another one fetch will be executed return;//so to avoid infinite loops i need to check the depth of request - if it more then 2 - return if (context.MessageName == "Execute" && context.InputParameters.Contains("FetchXml")) { XmlDocument indoc = new XmlDocument(); indoc.LoadXml((string)context.InputParameters["FetchXml"]); //Retrieve name of entity to display string entityName = indoc.SelectSingleNode("//fetch/entity").Attributes["name"].InnerText; //Creation of Metadata service - it will be need for retrieving of main attribute of entity MetadataService mservice = GetMetadataService(context.OrganizationName); RetrieveEntityRequest request = new RetrieveEntityRequest(); request.RetrieveAsIfPublished = false; request.LogicalName = entityName; request.EntityItems = EntityItems.EntityOnly; string primaryFieldName = ((RetrieveEntityResponse)mservice.Execute(request)).EntityMetadata.PrimaryField; CorrelationToken ct = new CorrelationToken(context.CorrelationId, context.Depth, context.CorrelationUpdatedTime); //CrmService Creation CrmService crmService = GetCrmService(context.OrganizationName, ct); crmService.CrmAuthenticationTokenValue.CallerId = context.InitiatingUserId; //Count of records by page - for calculation of pages count int pagecount = int.Parse(indoc.DocumentElement.Attributes["count"].InnerText); //I remove this attributes for retrieve of all records in current view indoc.DocumentElement.Attributes.Remove(indoc.DocumentElement.Attributes["count"]); indoc.DocumentElement.Attributes.Remove(indoc.DocumentElement.Attributes["page"]); //Xml of full result (without paging) string fullResult = crmService.Fetch(indoc.OuterXml); XmlDocument fullResultDocument = new XmlDocument(); fullResultDocument.LoadXml(fullResult); //Total record count by fetch int totalRecordCount = fullResultDocument.SelectNodes("//resultset/result").Count; int totalPageCount = (totalRecordCount / pagecount) + ((totalRecordCount % pagecount) == 0 ? 0 : 1); string result = string.Format("Total records = {0}, Total pages = {1}", totalRecordCount, totalPageCount); //Result XML which is the result shown in Grid XmlDocument outdoc = new XmlDocument(); outdoc.LoadXml((string)context.OutputParameters["FetchXmlResult"]); //Creation of record which will show totals XmlNode resResult = outdoc.CreateNode(XmlNodeType.Element, primaryFieldName, null); resResult.InnerText = result; XmlNode res = outdoc.CreateNode(XmlNodeType.Element, "result", null); res.AppendChild(resResult); //Adding record with label of count of pages and records as a first record in recordset outdoc.SelectSingleNode("//resultset").InsertBefore(res, outdoc.SelectSingleNode("//resultset").FirstChild); context.OutputParameters["FetchXmlResult"] = outdoc.OuterXml; } } #endregion private CrmService GetCrmService(string OrgName, CorrelationToken ct) { CrmAuthenticationToken token = new CrmAuthenticationToken(); token.AuthenticationType = AuthenticationType.AD; token.OrganizationName = OrgName; CrmService crmService = new CrmService(); crmService.UseDefaultCredentials = true; crmService.Url = (string)(Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\MSCRM").GetValue("ServerUrl")) + "/2007/crmservice.asmx"; crmService.CrmAuthenticationTokenValue = token; crmService.CorrelationTokenValue = ct; return crmService; } private MetadataService GetMetadataService(string OrgName) { MetadataService result = new MetadataService(); result.Url = (string)(Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\MSCRM").GetValue("ServerUrl")) + "/2007/MetadataService.asmx"; result.Credentials = System.Net.CredentialCache.DefaultCredentials; CrmAuthenticationToken token = new CrmAuthenticationToken(); token.OrganizationName = OrgName; token.AuthenticationType = 0; result.CrmAuthenticationTokenValue = token; result.UnsafeAuthenticatedConnectionSharing = true; return result; } } }
Build library, register it onto Execute message on Post Stage.
I don't see for what pay something about 500$... May be i'm stupid?
Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.com- Edited by Andrii ButenkoMVP, Moderator Wednesday, May 6, 2009 12:30 PM
Wednesday, May 6, 2009 12:28 PMModerator
All replies
-
Hi,
great sample code! Thank you!
Three additions:
1.) Is the a special reason not to use something like "ICrmService crmService = context.CreateCrmService(true);"?
2.) This is not for associated views.
3.) The result is only written in the Primary Field. It would be nicer to have it in the first column.
Thank you again for this great sample code!
Best regards,
Jürgen
Jürgen Beck
Dipl. Kfm./Wirtschaftsinformatik
MVP, MCSD.NET, MCITP DBA, MCDBA, MCSE
Microsoft Certified Business Management Solutions Professional
Microsoft Certified CRM Developer
Microsoft Certified Trainer
ComBeck IT Services & Business Solutions
Microsoft Gold Certified Partner
Microsoft Small Business Specialist
Developing & Supporting Business Applications from small business to big enterprises covering scores of sectors
http://www.combeck.de
Wednesday, May 6, 2009 1:06 PMModerator -
Hi, Jürgen
I wrote this plugin as a sample that to write such plugin isn't a problem.
Using CrmService - when a began work as CRM Developer - near half year ago - i had some problems with "ICrmService crmService = context.CreateCrmService( true ); " code. Don't remember waht problems...
Code can be modified in any way. Make result to the first field - 15 minutes of work =)
Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.comWednesday, May 6, 2009 1:12 PMModerator -
Hi,
there were problems with this because "localhost" was use in Standard what is not alway correct. But this is solved with UR3.
Best regards,
Jürgen
Jürgen Beck
Dipl. Kfm./Wirtschaftsinformatik
MVP, MCSD.NET, MCITP DBA, MCDBA, MCSE
Microsoft Certified Business Management Solutions Professional
Microsoft Certified CRM Developer
Microsoft Certified Trainer
ComBeck IT Services & Business Solutions
Microsoft Gold Certified Partner
Microsoft Small Business Specialist
Developing & Supporting Business Applications from small business to big enterprises covering scores of sectors
http://www.combeck.de
Wednesday, May 6, 2009 1:26 PMModerator -
Hi, Jürgen.
For assosiated views RetrieveMultiple message plugin can be used. It's a bit different, but it also not difficult =)
Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.comWednesday, May 6, 2009 2:22 PMModerator -
Can you give a little more info on what this code does? Is it counting the total records in a view and displaying it somewhere?Wednesday, May 6, 2009 3:37 PM
-
Can you give a little more info on what this code does? Is it counting the total records in a view and displaying it somewhere?
Hi.
Look this screenshop . There are total records and pages count on the first row of view.
Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.comWednesday, May 6, 2009 4:11 PMModerator -
Thank you soo much :-) it will help me alot
Thanks, AarchThursday, May 7, 2009 7:26 AM -
Additionally it is to add that the information is displayed in the Primary Field column.
When there is no Primary Field column displayed there is no information visible.
Best regards,
Jürgen
Jürgen Beck
Dipl. Kfm./Wirtschaftsinformatik
MVP, MCSD.NET, MCITP DBA, MCDBA, MCSE
Microsoft Certified Business Management Solutions Professional
Microsoft Certified CRM Developer
Microsoft Certified Trainer
ComBeck IT Services & Business Solutions
Microsoft Gold Certified Partner
Microsoft Small Business Specialist
Developing & Supporting Business Applications from small business to big enterprises covering scores of sectors
http://www.combeck.de
Thursday, May 7, 2009 8:02 AMModerator -
Hi,
there is an error with the automatic lookup resolution. If you type something in a lookup there comes a general error.
Best regards,
Jürgen
Jürgen Beck
Dipl. Kfm./Wirtschaftsinformatik
MVP, MCSD.NET, MCITP DBA, MCDBA, MCSE
Microsoft Certified Business Management Solutions Professional
Microsoft Certified CRM Developer
Microsoft Certified Trainer
ComBeck IT Services & Business Solutions
Microsoft Gold Certified Partner
Microsoft Small Business Specialist
Developing & Supporting Business Applications from small business to big enterprises covering scores of sectors
http://www.combeck.de
Friday, May 8, 2009 7:35 AMModerator -
-
Hi, Jürgen and Nishant
I found another one bug - Service calendar doesn't work. My code is the base based on which enyone can create, modify and update existing functionality. It's not a release. Just code sample ) It's just attempt to show mighty of MS CRM Core =)
Истина открывается подготовленному уму. Мой блог - http://a33ik.blogspot.comFriday, May 8, 2009 8:25 AMModerator -
Hi,
That's true, the code sample is meant for guiding others!!
Thanks again !
Regards,
Nishant Rana
http://nishantrana.wordpress.comFriday, May 8, 2009 8:37 AM -
We have developed a complete record and page counter solution that seamlessly and easily integrated into CRM. The GI RCO counter supports all CRM views including auto resolve lookup and form assistant.
I made it publicly available under a very appealing royalty free distribution license so partners will find it worthwhile and won’t waste time and money on trying to recreate this functionality which eventually costs more to develop then acquiring the source code.
The Counter was already implemented successfully at live customers with hundreds of thousands of records. It works really fast and has minimal performance impact.
The counter supports associated views and displaying of summery results on any given column.
You can find more information, a video demonstration and images of supported views at my blog.
Blog: http://mscrm4ever.blogspot.com/ * Website: http://gicrm.upsite.co.il/Friday, May 8, 2009 11:43 AM -
HI,
interesting sample code.
Have You figured out how to catch the rollup message to count activities or cases related to an entity?
Cherrs,
NorbTuesday, May 12, 2009 6:32 PM -
Hi, Norbert.
I've not enough time to solve this task, but it seems that to solve your question new plugin on RetrieveMultiple message must be created, but i'm not sure...
Truth opens to prepared mind. My blog - http://a33ik.blogspot.comTuesday, May 12, 2009 6:35 PMModerator -
Hi, all.
I've fixed issues for previous version of Record counter and now it is available here .
Truth is opened the prepared mind My blog - http://a33ik.blogspot.comThursday, September 3, 2009 3:29 PMModerator -
Hi, all.
I've fixed issues for previous version of Record counter and now it is available here .
Truth is opened the prepared mind My blog - http://a33ik.blogspot.comYour way of calculating the records is wrong:1. If there are more than 5000 record your counter will show only 5000.2. Even if it did work, your plugin has major performance issues. You shouldn't retrieve all the entities and count the nodes. You should manipulate the original query to become a count query and work with that.Friday, September 4, 2009 11:57 AM -
Hi, Moti.
Thanks for your comment. I've modified code of the plugin and now it works even count of records is greater then 5000.
One more time - thanks!
Truth is opened the prepared mind My blog - http://a33ik.blogspot.comSunday, September 6, 2009 11:29 AMModerator -
You are very welcome.Sunday, September 6, 2009 12:46 PM
-
//make sure we don't put this into a status or Guid field as it will error
XmlNode node=outdoc.SelectSingleNode("//resultset").FirstChild); if (node.Attributes.Count > 0 || node.Name.EndsWith("id"))Monday, September 7, 2009 6:07 AM -
i recommende you to use this code: i use stunwware fetc library http://linqtocrm.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24377 int pageSize; public void Execute(IPluginExecutionContext context) { string originalFetch = context.InputParameters.Properties["FetchXml"].ToString(); var fetchStatement = FetchStatement.FromXml(originalFetch); string entityName = fetchStatement.Entity.EntityName; //This since our call to get the count will cause this method to //get called again, this prevents from getting into an infinite loop bool isRecordcount = originalFetch.Contains("GridRecordCounter"); if (isRecordcount) { return; } pageSize = fetchStatement.PageCount; //Clear all columns, turn off all columsn if specififed. if (fetchStatement.Entity.Columns.AllColumns == false) { fetchStatement.Entity.Columns.Columns.Clear(); } else { fetchStatement.Entity.Columns.AllColumns = false; } //Clear link entity attributes if (fetchStatement.Entity.LinkEntities.Count > 0) { fetchStatement.Entity.LinkEntities.Clear(); } //Clear any order by clauses fetchStatement.Entity.Orders.Clear(); //Change to an aggragate function fetchStatement.PageCount = 0; fetchStatement.Aggregate = true; fetchStatement.PagingCookie = null; //use createdby since all entities should have this field and have it populated fetchStatement.Entity.Columns.Columns.Add("createdby"); fetchStatement.Entity.Columns.Alias = "GridRecordCounter"; fetchStatement.Entity.Columns.Aggregate = FetchAggregate.Count; ICrmService service = context.CreateCrmService(true); string response = service.Fetch(fetchStatement.ToString()); XmlDocument doc = new XmlDocument(); doc.LoadXml(response); doc.LoadXml(response); string recordCountValue = doc.GetElementsByTagName("GridRecordCounter").Item(0).InnerText; if (!string.IsNullOrEmpty(recordCountValue) && recordCountValue != "0") { int recordCount = Convert.ToInt32(recordCountValue); if (recordCount < pageSize) return; XmlDocument resultDoc = new XmlDocument(); string originalResponse = context.OutputParameters.Properties["FetchXmlResult"].ToString(); resultDoc.LoadXml(originalResponse); XmlNode resultSet = resultDoc.SelectSingleNode("resultset"); if (resultSet.HasChildNodes) { XmlNode newNode = resultSet.ChildNodes[0].CloneNode(true); int count = 0; //Clear old data from copied node and put text in first string field bool nodeUsed = false; foreach (XmlNode node in newNode.ChildNodes) { bool nodeUsable = true; //make sure we don't put this into a status or Guid field as it will error if (node.Attributes.Count > 0 || node.Name.EndsWith("id")) { node.Attributes.RemoveAll(); nodeUsable = false; } if (nodeUsable && !nodeUsed && pageSize!=0) { nodeUsed = true; double totalPages = Math.Ceiling(Convert.ToDouble(recordCount / pageSize)); node.InnerText = String.Format("Total Records: {0}, Pages: {1}", recordCount, totalPages); } else { node.InnerText = null; } count++; } if (nodeUsed) { resultSet.InsertBefore(newNode, resultSet.ChildNodes[0]); } context.OutputParameters.Properties["FetchXmlResult"] = resultSet.OuterXml; } } }Monday, September 7, 2009 6:13 AM
-
Thank you, Hassan. I will try your code.
Truth is opened the prepared mind My blog - http://a33ik.blogspot.comMonday, September 7, 2009 5:24 PMModerator -
HI,
interesting sample code.
Have You figured out how to catch the rollup message to count activities or cases related to an entity?
Cherrs,
Norb
Hi, Norb.
I've figured out to handle rollup message but in unsupported meaner. Check this url .
Truth is opened the prepared mind
My blog (english)
Мой блог (русскоязычный)Monday, January 11, 2010 10:47 AMModerator -
Hi Andriv,
Nice Stuff.
Just curious, would you ever considered querying the SQL DB directly for performance reasons and built in features such as sql 'count'? By querying filtered views you would still be using the same security model as when using the web services. Otherwise nice stuff, thanks.
Karlo
Karlo Swart - http://www.ver206.comMonday, January 11, 2010 11:03 AM -
Hello all.
I redeveloped code of record counter and fixed several errors. You can find it here - http://a33ik.blogspot.com/2010/08/record-record-counter-for-microsoft.html
Microsoft CRM Freelancer
My blog (english)
Мой блог (русскоязычный)Monday, August 30, 2010 11:13 PMModerator