Useful CRM 2011 .NET extension methods

Hello guys,

This will be pretty straight forward. In order to use the extension methods below in C# for CRM 2011 development, such as plugins, custom workflow actions, windows services or any other type of CRM SDK based application, you need to follow these steps:

1. Download the latest CRM SDK here.

2. Navigate to ~\sdk\bin\ and check you got the crmsvcutil.exe utility there.

3. Run Command Prompt (cmd) as Administrator and navigate to the ~\sdk\bin\ folder (where crmsvcutil.exe is found) and type:

CrmSvcUtil.exe /url:http://://xrmServices/2011/Organization.svc /out:EarlyBoundCRMClasses.cs /username: /password: /domain: /namespace:CRMSDK /serviceContextName:MyCrmServiceContext

This will generated a .cs file named EarlyBoundCRMClasses.cs which contains all CRM objects for later early bound use.

4. Open Visual Studio (2010 or 2012) and add the class you’ve just created to your project. Also, add these 2 sdk libraries as references: microsoft.crm.sdk.proxy and microsoft.xrm.sdk (they can be found in the same ~\sdk\bin\ folder).

5. Create a new public static class named Extensions.cs and copy-paste the following code in it:

public static class Extensions
{
#region Properties
/// 
/// CRM Service
/// 
public static IOrganizationService Service { get; set; }
#endregion

#region Methods
/// 
/// Gets a certain attribute schema name, based on early-bound record property
/// 
///Entity Type
///Record Early-Bound Attribute
///Record
///Record Early-Bound Attribute
/// 
public static string GetAttributeName(this T record, Expression> attribute)
where T : Entity
{
    MemberExpression memberExpression = (MemberExpression)attribute.Body;
    var member = memberExpression.Member;	

    var nameAttributes = member.GetCustomAttributes(typeof(AttributeLogicalNameAttribute), true);
    if (nameAttributes != null && nameAttributes.Length > 0)
    {
	var logicalName = (nameAttributes[0] as AttributeLogicalNameAttribute).LogicalName;
	return logicalName;
    }

    throw new ArgumentException(string.Format("{0} is not a CRM property of entity {1}", member.Name, typeof(T).Name));
}

/// 
/// Gets the primary attribute schema name for the current entity
/// 
///Entity
public static string GetPrimaryAttributeName(this Entity entity)
{
    if (Service != null)
    {
	RetrieveEntityRequest req = new RetrieveEntityRequest() { LogicalName = entity.LogicalName, EntityFilters = Microsoft.Xrm.Sdk.Metadata.EntityFilters.Attributes, RetrieveAsIfPublished = true };

	RetrieveEntityResponse response = (RetrieveEntityResponse)Service.Execute(req);

	if (response != null && response.EntityMetadata != null)
	    return response.EntityMetadata.PrimaryNameAttribute;
    }

    return string.Empty;
}

/// 
/// Converts the current list to integer-valued list
/// 
///List
public static List ToIntegerList(this List list)
{
    List result = new List();

    if (list != null && list.Count > 0)
    {
	list.ForEach(e =>
	{
	    int number = int.MinValue;

	    bool parsed = int.TryParse(e, out number);

	    if (number != int.MinValue)
		result.Add(number);
	});
    }

    return result;
}

/// 
/// Converts the current array to integer-valued array
/// 
///Array
public static int[] ToIntegerArray(this string[] array)
{
    return array.ToList().ToIntegerList().ToArray();
}

/// 
/// Converts a certain entity collection into a typed entity collection
/// 
///Source collection
public static EntityCollection ToCollection(this EntityCollection collection) where T : Entity, new()
{
    EntityCollection result = new EntityCollection();
    string entityName = typeof(T).Name;

    if (collection.Entities.Count > 0)
    {
	for (int i = 0; i < collection.Entities.Count; i++)
	{
	    Entity entity = collection.Entities[i];

	    T newEntry = new T() { LogicalName = entityName.ToLower() };

	    try
	    {
		if (typeof(T) == typeof(ActivityParty))
		    newEntry["partyid"] = entity.ToEntityReference();
		else
		    newEntry = entity.ToEntity();

		if (!result.Entities.Contains(newEntry))
		    result.Entities.Add(newEntry);
	    }
	    catch (Exception ex)
	    {
		// Invalid Cast
		throw new Exception(string.Format("Invalid Cast from {0} to {1}", entity.LogicalName, entityName), ex);
	    }
	}
    }

    result.EntityName = entityName;

    return result;
}

/// 
/// Converts a certain entity collection into activity party entity collection
/// 
///Source collection
public static EntityCollection ToActivityPartyCollection(this EntityCollection collection)
{
    return collection.ToCollection();
}

/// 
/// Gets the attribute name value-list for a certain entity list
/// 
///Entity Type
///Record list
///Attribute schema name
/// 
public static List ToAttributeList(this List records, string attributeName) where T : Entity
{
    List result = new List(records.Count);

    if (records.Count > 0)
    {
	try
	{
	    records.ForEach(r => result.Add(r.GetAttributeValue(attributeName)));
	}
	catch (Exception ex)
	{
	}
    }

    return result;
}

/// 
/// Gets the primary attribute name value-list for a certain entity list
/// 
///Entity Type
///Record list
public static List ToPrimaryAttributeList(this List records) where T : Entity
{
    List result = new List(records.Count);

    if (records.Count > 0)
    {
	string primaryAttributeName = records[0].GetPrimaryAttributeName();

	result = records.ToAttributeList(primaryAttributeName);
    }

    return result;
}
#endregion
}   

6. To use the extention methods created above, you can use the following usage examples (for some of them):

/// 
/// Get Active Accounts as Collection
/// 
public EntityCollection GetAccountsCollection(IOrganizationService service)
{
    if (service != null)
    {
	try
	{
	    ConditionExpression condition1 = new ConditionExpression();
	    condition1.AttributeName = "statecode";
	    condition1.Operator = ConditionOperator.Equal;
	    condition1.Values.Add(0); // Active

	    ConditionExpression condition2 = new ConditionExpression();
	    condition2.AttributeName = "name";
	    condition2.Operator = ConditionOperator.NotNull;

	    FilterExpression filter1 = new FilterExpression();
	    filter1.Conditions.Add(condition1);
	    filter1.Conditions.Add(condition2);
	    filter1.FilterOperator = LogicalOperator.And;

	    QueryExpression query = new QueryExpression("account");
	    query.ColumnSet = new ColumnSet(true);
	    query.Criteria.AddFilter(filter1);

	    EntityCollection collection = service.RetrieveMultiple(query);

	    return collection;
	}
	catch (Exception ex)
	{
	    
	}
    }

    return null;
}

public void Test()
{
    // OrganizationProxy object won't be discussed in this chapter, let's assume you are already connected to your CRM organization and OrganizationProxy is a valid IOrganizationService object
    IOrganizationService organizationProxy = null; // GetOrganizationProxy();

    // Create a context object based on service & organization proxy           
    IOrganizationService service = (IOrganizationService)organizationProxy;
     MyCrmServiceContext   context = new MyCrmServiceContext(service);

    // Retrieve accounts
    List accounts = context.AccountSet.ToList();

    // Get Account Names
    List accountNames = accounts.ToPrimaryAttributeList();
    Console.WriteLine(string.Format("Accounts are: {0}", string.Join(", ", accountNames)));

    // Get Phone Numbers
    List phoneNumbers = accounts.ToAttributeList("telephone1");
    Console.WriteLine(string.Format("Phone numbers are: {0}", string.Join(", ", phoneNumbers)));

    // Get Primary Attribute Name
    string accountPrimaryAttribute = accounts[0].GetPrimaryAttributeName();
    Console.WriteLine(string.Format("The primary attribute for account entity is: {0}", accountPrimaryAttribute));

    // Get Accounts Collection
    EntityCollection accountsCollection = GetAccountsCollection(service);

    // Cast Collection to ActivityParty (so it can be use in activity party lists, such as From & To for email entity)
    // Both extension methods will output same result, it's just a matter of taste
    EntityCollection activityPartyCollection1 = accountsCollection.ToActivityPartyCollection();
    EntityCollection activityPartyCollection2 = accountsCollection.ToCollection();
    
    // Out-of-scope
    // Converts a list or an array of strings to list or array of integers
    List sampleStringList = new List() { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
    List sampleIntList = sampleStringList.ToIntegerList(); // outputs list containing the 10 digits
    int[] sampleIntArray = sampleStringList.ToArray().ToIntegerArray(); // outputs array containing the 10 digits
}

7. Hope you’ll find these useful 🙂 Don’t forget to rate this post and visit our official facebook page.

 

Thank you,

Cornel

Leave a comment

Your email address will not be published. Required fields are marked *