Recently viewed items Performance issue/bug.
Today I want to share with you one of the Microsoft's Dynamics CRM issues that causes a serious performance issue.
RECENTLY VIEWED XML
If you are suffering from bad performance while the CRM form opens, I suggest you to check your RecentlyViewedXml, you might be surprised.
RecentlyViewedXml is an attribute of the UserEntityUISettings Entity. It describes which items are most recently viewed per entity. This data helps the CRM show us the recently viewed records under the "Recently viewed items" button on the navigation bar.
PROBLEM
The problem is that the RecentlyViewedXml saves almost all the history, so the xml's can take up dozens, or even hundreds of MB! And this data is coming from the server every time you open the form!
DIAGNOSIS
First, to check what's the status of your system is, run this query:
SELECT MAX(LEN(U.RecentlyViewedXml)), U.OwnerIdName
FROM UserEntityUISettings U
GROUP BY U.OwnerIdName
HAVING MAX(LEN(U.RecentlyViewedXml)) > 200000
ORDER BY MAX(LEN(U.RecentlyViewedXml)) DESC
The query returns the max length of the RecentlyViewedXml for each user only for big records (according to Microsoft consultant – 200,000 chars is the limit). If the query returns results, then:
" Houston, We've Got a Problem!"
SOLUTION
We wrote a Console Application that runs once a week and handles the UserEntityUISettings table.
This console keep's the latest x items and removes the others, but, we don't touch the pinned items. What are the pinned items? These are the items the user pinned – to keep always on the top:
And finally we update the RecentlyViewedXml field.
CODE
- Retrieve all UserEntityUISettings records of active users that contains RecentlyViewedXml:
var userEntityUISettings =
(from u in contectService.UserEntityUISettingsSet
join s in contectService.SystemUserSet on u.OwnerId.Id equals s.SystemUserId
where s.IsDisabled == false
where u.RecentlyViewedXml != null
select new UserEntityUISettings
{
UserEntityUISettingsId = u.UserEntityUISettingsId,
RecentlyViewedXml = u.RecentlyViewedXml
}).ToList();
2. Parse the xml and leave only X last viewed items (we declared 20):
foreach(var userSettings in userEntityUISettings)
{
var recentlyXml = XElement.Parse(userSettings.RecentlyViewedXml);
var recentlyItems = recentlyXml.Descendants("RecentlyViewedItem").ToList();
//number of pinned recently viewed items
var pinnedCount = recentlyItems.Where(x => x.Element("PinStatus").Value == "true").Count();
//Unpinned recently viewed items
var unPinned = recentlyItems
.Where(x => x.Element("PinStatus").Value == "false")
.Select(x => x)
.OrderByDescending(x => DateTime.Parse(x.Element("LastAccessed").Value, CultureInfo.InvariantCulture))
.ToList();
if (pinnedCount + unPinned.Count >= maxItems) {
//Remove all recently viewed items except last 'maxItems' items
unPinned.Skip(maxItems - pinnedCount).ToList().ForEach(x => x.Remove());
userSettings.RecentlyViewedXml = recentlyXml.ToString();
contectService.DeleteObject(userSettings);
contectService.UpdateObject(userSettings);
}
}
contectService.SaveChanges();
localStorage:
After you run this console, you will be surprised to see that the recently Viewed items are still there!
Why? Because of the localStorage. What is the localStorage? The localStorage is a browser property that allows to save key/value pairs in a web browser. It stores data with no expiration date. The data will not be deleted when the browser is closed, and will be available the next day, week, or year!
Clear localStorage:
You have a several of options:
1. Clear from the Developer Tools console: Press F12, select "Console" and run: "localStorage.clear()".
2. Open "Delete Browsing History" (Ctrl + Shift + Delete):
Make sure "Cookies and website data" is selected and Press "Delete".
SUMMARY
Microsoft is aware to this problem, but until they will fix that, this is my solution.
Thanks,
Ziv Ben-Or
+972545882011
Spécialiste Dynamics 365 CE / Dynamics 365 CE Specialist @ CGI
6 年FYI, 8.2.3 release includes fix for this issue. We are testing it now.
Microsoft Power Platform and Dynamics 365 Solution Architect
6 年Struggled with this the whole day and found your post. I was using Google Chrome Performance metrics to come to the same conclusion as you did.? There are two different endpoints that the website is calling each time a record loads which was picked up in the performance metrics. They were?AppWebServices/RecentlyViewedWebService.asmx and?form/Data.aspx - So I cleared the Application Storage cache in Chrome, did an OrganizationService fix to the userentityuisettings record and restarted IIS in between. Restarted the user's PC as well in the end (which gave me time to do the other things).? The LEN(RecentlyViewedXml) was over 8 000 000 in size for one user and had 140 000 contacts listed for ObjectTypeCode 2. I also reverse engineered the bin folder DLL's from Microsoft Dynamics CRM and found they are using a Dictionary to store the values in with no usage of the MaxViewCount = 10 nor MaxEntityCount = 40 in?namespace Microsoft.Crm.Application.Utility.RecentlyViewedList It was taking over 2min to load a record and after the fix it now loads instantly. After monitoring the new value, it has resetted and starting to increase slowly... Thank you for the post
Dynamics 365, Azure, SSIS, SSRS .Net,
6 年It's need IIS reset to reflect the changes. Thanks for the fix.?
Spécialiste Dynamics 365 CE / Dynamics 365 CE Specialist @ CGI
6 年Thank you Ziv, this helped us tremendously! In a case management environment where an agent can go through hundreds of records (cases, tasks, emails, etc.), the performance hit caused by the issue was such that a save operation that should have taken 1 second can take 30-60 seconds!