Pieter van der Westhuizen

Microsoft Dynamics CRM and Add-in Express 2010, part 3

When most organisations buy MS Dynamics CRM they probably already made an investment in systems to help them manage their business processes. In this post I’ll demonstrate how you can use Add-in Express 2010 to easily leverage Northwinds’ (Our Customer) existing web ordering system and import orders received from the internet into MS Dynamics CRM from within MS Outlook.

First, some background: Northwind has an existing web ordering system, which enables their customers to order products online. After these orders have been submitted, it is automatically emailed to the customers’ associated sales representative. Once the sales representative received the email, she then manually captures the order into Northwinds’ ordering system. Below is an example of how the order e-mail looks like:

Sample order e-mail

In order to do this, we create a new ADX COM Add-in project in Visual Studio 2010.

Creating a new COM Add-in for Outlook

Once you’ve completed the new project wizard, open the AddinModule‘s designer, by double-clicking on the AddinModule.cs file. Add a new ADXRibbobTab component by clicking on its item on the designer toolbar:

Adding a new ribbon tab

Add a new RibbonGroup to the RibbonTab and a RibbonButton to the RibbonGroup. Our RibbonTab will look like this:

Custom ribbon tab

You’ll notice by default the RibbonTabs’ Ribbons property is set to OutlookMailRead and OutlookMailCompose. Leave that as is for this example. Next, we need some code to parse the e-mail text and create the order in CRM. Select the RibbonButton you’ve added and double-click in its OnClick event in the property window in order to generate the event code.

Add the following to the click event handler:

private void btnSendToCRM_OnClick(object sender, AddinExpress.MSO.IRibbonControl control, bool pressed)
{
Outlook.Inspector myInspector = (Outlook.Inspector)OutlookApp.ActiveInspector();
Outlook.MailItem currMail = (Outlook.MailItem)myInspector.CurrentItem;
 
string bodyText = currMail.Body;
Order newOrder = new Order();
 
StringCollection lines = new StringCollection();
StringReader reader = new StringReader(bodyText);
while (!(reader.Peek() == -1))
{
    lines.Add(reader.ReadLine());
}
reader.Close();
reader.Dispose();
 
newOrder.CustomerId = lines.Find("Customer Id: ").Replace("Customer Id: ", "");
newOrder.OrderDate = lines.Find("Date Ordered: ").Replace("Date Ordered: ", "");
 
int productsStart = lines.IndexOf("PRODUCTS ORDERED")+1;
int productsEnd = lines.IndexOf("END OF PRODUCTS ORDERED")-1;
 
for (int i = productsStart; i <= productsEnd; i++)
{
    string[] product = lines[i].Split('x');
    OrderDetail orderDetail = new OrderDetail();
    orderDetail.ProductName = product[1].Trim();
    orderDetail.Quantity = Convert.ToInt32(product[0]);
    newOrder.OrderDetails.Add(orderDetail);
}
Marshal.ReleaseComObject(myInspector);
Marshal.ReleaseComObject(currMail);
SendToCrm(newOrder);
}

In this code, we use Outlooks’ ActiveInspector object to access the current open mail item. We load the body text into a string collection and populate a custom order class from the information in the e-mail. Finally we call a method to create an order in MS Dynamics CRM:

private void SendToCrm(Order order)
{
    CrmService crmService = InitCRM();
    Guid accountId = GetCRMAccountId(order.CustomerId, crmService);
    Guid orderId = CreateCRMOrder(accountId, crmService);
 
    foreach (OrderDetail detail in order.OrderDetails)
    {
        Guid productid = GetCRMProductId(detail.ProductName, crmService);
        CreateCRMOrderDetail(orderId, productid, detail.Quantity, crmService);
    }
}

In the above method we initialize the CRM service and split up the process of creating the order into different methods:

  • GetCRMAccountId retrieves the unique id of the customer account in CRM;
  • CreateCRMOrder creates the order in CRM and returns the unique order id;
  • from there we loop through the products bought;
  • retrieves the CRM id for the product (GetCRMProductId); and
  • create a CRM Orderdetail record for each item with the CreateCRMOrderDetail method.

I’ve listed the code for the methods below:

private CrmService InitCRM()
{
    CrmAuthenticationToken token = new CrmAuthenticationToken();
    token.AuthenticationType = 0;
    token.OrganizationName = "NorthwindTraders";
 
    CrmService crmService = new CrmService();
    crmService.Url = "http://crmserver:5555/mscrmservices/2007/crmservice.asmx";
    crmService.CrmAuthenticationTokenValue = token;
    crmService.Credentials = new System.Net.NetworkCredential("UserName", "Password", "CRMSERVER");
 
    return crmService;
}
 
private Guid GetCRMAccountId(string accountName, CrmService crmService)
{
    Guid accountId = new Guid();
 
    ConditionExpression condition = new ConditionExpression();
    condition.AttributeName = "accountnumber";
    condition.Operator = ConditionOperator.Equal;
    condition.Values = new string[] { accountName };
 
    FilterExpression filter = new FilterExpression();
    filter.FilterOperator = LogicalOperator.And;
    filter.Conditions.Add(condition);
 
    QueryExpression query = new QueryExpression();
    query.EntityName = EntityName.account.ToString();
    query.ColumnSet = new ColumnSet(new string[] { "accountid" });
    query.Criteria = filter;
 
    BusinessEntityCollection accounts = crmService.RetrieveMultiple(query);
    foreach (BusinessEntity Account in accounts.BusinessEntities)
    {
        accountId = ((account)Account).accountid.Value;
    }
    return accountId;
}
 
private Guid CreateCRMOrder(Guid accountId, CrmService crmService)
{
    Guid orderId = Guid.NewGuid();
    salesorder newOrder = new salesorder();
    newOrder.customerid = new Customer(EntityName.account.ToString(), accountId);
    newOrder.pricelevelid = new Lookup(EntityName.pricelevel.ToString(), new Guid("60E76547-CA97-DF11-A606-0003FFB96A35"));
    newOrder.name = "Online Order";
    orderId = crmService.Create(newOrder);
    return orderId;
}
 
private Guid GetCRMProductId(string productName, CrmService crmService)
{
    Guid productId = new Guid();
 
    ConditionExpression condition1 = new ConditionExpression();
    condition1.AttributeName = "name";
    condition1.Operator = ConditionOperator.Equal;
    condition1.Values = new string[] { productName };
 
    FilterExpression filter1 = new FilterExpression();
    filter1.FilterOperator = LogicalOperator.And;
    filter1.Conditions.Add(condition1);
 
    QueryExpression query1 = new QueryExpression();
    query1.EntityName = EntityName.product.ToString();
    query1.ColumnSet = new ColumnSet(new string[] { "productid" });
    query1.Criteria = filter1;
 
    BusinessEntityCollection products = crmService.RetrieveMultiple(query1);
    foreach (BusinessEntity Product in products.BusinessEntities)
    {
        productId = ((product)Product).productid.Value;
    }
    return productId;
}
 
private void CreateCRMOrderDetail(Guid orderId, Guid productId, decimal quantity, CrmService crmService)
{
    salesorderdetail orderDetail = new salesorderdetail();
    orderDetail.productid = new Lookup(EntityName.product.ToString(), productId);
    orderDetail.quantity = new CrmDecimal(quantity);
    orderDetail.salesorderid = new Lookup(EntityName.salesorder.ToString(), orderId);
    orderDetail.uomid = new Lookup(EntityName.uom.ToString(), new Guid("BD4255CF-27EC-456B-9534-B738CC4BDDD3"));
    crmService.Create(orderDetail);
}

If all goes well, when an order comes in via e-mail, all the sales representative needs to do, is click the ribbon button and the order will automatically be created in MS Dynamics CRM:

Sample order e-mail

Thank you for reading. Until next time, keep coding!

You may also be interested in:

Microsoft Dynamics CRM and Add-in Express 2010, part 2
Microsoft Dynamics CRM and Add-in Express 2010, part 1

Post a comment

Have any questions? Ask us right now!