Wednesday, 17 April 2013

Sort sitemap alphabetically according to Display name in MS Dynamics CRM 2011

A handy little class to sort a sub area of the sitemap in alphabetical order according to Display name rather than logical name.  Major Area refers to Workplace, Settings, etc.. whereas minor Area refers to the sub areas inside this, e.g. extensions.

I think it should be possible to do them in reverse alphabetical order by using the reverse() method when selecting the items, but I haven't tried. Not sure what kind of customer would want reverse alphabetical order though, as it seems counter intuitive, but there you go.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;

public class SitemapSorter
{
    [ThreadStatic]
    private IOrganizationService service;

    public SitemapSorter(IOrganizationService service)
    {
        this.service = service;
    }

    public void Sort(string file, string majorArea, string minorArea)
    {
        XDocument xdoc = XDocument.Load(new StreamReader(file));

    //Get XElements in the relevant area (Workplace -> Extensions in this case)
    //Store them in a Dictionary. key is the Display name and the value is the
    //entire node (XElement).
    var nodes = xdoc.Root.Descendants("Area")
        .Where(x => x.FirstAttribute.Value == majorArea)
        .Descendants("Group")
        .Where(x => x.FirstAttribute.Value == minorArea)
        .Descendants()
        .ToDictionary(x => RetriveDisplayName(service, x.LastAttribute.Value), x => x);
              
    //Use a Sorted Dictionary, which will automatically sort on key,not on value.
    SortedDictionary<string, XElement> items = new SortedDictionary<string, XElement>(nodes);
              
    //Remove the nodes from sitemap document
    xdoc.Root.Descendants("Area")
       .Where(x => x.FirstAttribute.Value == majorArea)
       .Descendants("Group")
       .Where(x => x.FirstAttribute.Value == minorArea)
       .Descendants().Remove();
              
    //Now add them in order
    xdoc.Root.Descendants("Area")
       .Where(x => x.FirstAttribute.Value == majorArea)
       .Descendants("Group")
       .Where(x => x.FirstAttribute.Value == minorArea)
       .First().Add(items.Select(x => x.Value));

    xdoc.Save(file);
    }

    private string RetriveDisplayName(IOrganizationService service, string entityName)
    {
    string result = string.Empty;
    try
    {
        RetrieveEntityRequest request = new RetrieveEntityRequest()
        {
            EntityFilters = EntityFilters.Entity,
            LogicalName = entityName
        };
        RetrieveEntityResponse response =
            (RetrieveEntityResponse)service.Execute(request);
        result = response.EntityMetadata.DisplayName.UserLocalizedLabel.Label;
    }
    catch (Exception ex)
    {
        CommonHelper.LogException(ex);
    }
    return result;
    }
}

No comments:

Post a Comment