Friday, October 30, 2009

Creating a Birthday Contact List

Microsoft Dynamics CRM Team Blog

Today we welcome our guest blogger CRM MVP Darren Liu from the Crowe Horwath company.

Have you ever been asked by someone to get a list of contacts having birthdays during a certain time period from CRM? If so what have you done to perform this task? Within the application, birthdays are tracked on Contact records as a single date (including year). This causes problems when searching for birthdays in a certain time period as the birth date is evaluated including the year. To illustrate, consider the following example:

· John Dole, 10/1/1980

· Adam Smith, 9/1/1970

· Mark Francis, 10/10/1960

Within CRM, searching for date is done by range. There is no easy way to identify from the above contacts all those having birthday in October as any range you choose will include the year. Wildcard functions on date fields are not a workable solution.

There are several solutions to this problem including JavaScript to parse birthday on the onChange event, a custom report or a plug-in. The desired functionality is to be able to search by birth month, birth day, and/or birth year, allowing the user to quickly identify all birthdays in a certain time period.

In this blog, I will show you how to use a pre plug-in to parse the birthday field into day, month and year. This way, the users will able to perform searches using Advanced Find. I have chosen the plug-in approach because it will help me parse the birthday field not only when the users update the birthday on the contact form but also when updating the birthday through the CRM web service for data imports and data integration.

Implement the pre plug-in

1. Create New Attributes

Create three new attribute on the Contact entity form in CRM. After creating the new attributes, publish the Contact customization.

Display Name

Schema Name

Type

Searchable

Values

Birth Month

new_birthmonth

Picklist

Yes

Jan = 1, Feb = 2, Mar = 3, Apr = 4, May = 5, Jun = 6, Jul = 7, Aug = 8, Sept = 9, Oct = 10, Nov = 11, Dec = 12

Birth Day

new_birthday

Int

Yes

Min Value = 1

Max Value = 31

Birth Year

new_birthyear

Int

Yes

Min Value = 1900

Max Value = 9999

clip_image002

2. Create pre plug-in using Visual Studio

Create a plug-in project name Crm.Plugin, copy and paste the following code to your Plug-in project.

using System;


using System.Collections.Generic;


using System.Text;


using Microsoft.Crm.Sdk;


using Microsoft.Crm.SdkTypeProxy;


 


namespace Crm.Plugin


{


  public class MonthDayYearContactPlugin : IPlugin


  {


    public void Execute(IPluginExecutionContext context)


    {


    DynamicEntity entity = null;


 


    if (context.InputParameters.Properties.Contains(ParameterName.Target) &&


        context.InputParameters.Properties[ParameterName.Target] is DynamicEntity)


    {


        entity = (DynamicEntity)context.InputParameters[ParameterName.Target];


        if (entity.Name != EntityName.contact.ToString()) { return; }


    }


    else


    {


        return;


    }


 


    try


    {


        if (entity.Properties.Contains("birthdate"))


        {


            CrmDateTime _birthdate = (CrmDateTime)entity["birthdate"];


            if (_birthdate.IsNull)


            {


                entity["new_birthday"] = CrmNumber.Null;


                entity["new_birthmonth"] = Picklist.Null;


                entity["new_birthyear"] = CrmNumber.Null;


            }


            else


            {


                DateTime birthdayValue = _birthdate.UserTime; 


                entity["new_birthday"] = new CrmNumber(birthdayValue.Day);


                entity["new_birthmonth"] = new Picklist(birthdayValue.Month);


                entity["new_birthyear"] = new CrmNumber(birthdayValue.Year);


            }


        }


    }


    catch (Exception ex)


    {


        throw new InvalidPluginExecutionException("An error occurred in the Month, Day, Year Plug-in for Contact.", ex);


    }


    }


  }


}


3. Register the plug-in The last step is to register the plug-in. To register the plug-in, you may use the Plug-in Registration tool from the MSDN Code Gallery. After the assembly is uploaded, you need to associate the following steps to the plug-in:



Message: Create


Primary Entity: contact


Filtering Attributes: birthdate


Eventing Pipeline Stage of Execution: Pre Stage


Execution Mode: Synchronous



Triggering Pipeline: Parent Pipeline



Message: Update


Primary Entity: contact


Filtering Attribute: birthdate


Eventing Pipeline Stage of Execution: Pre Stage


Execution Mode: Synchronous



Triggering Pipeline: Parent Pipeline



Message: Create


Primary Entity: contact


Filtering Attributes: birthdate


Eventing Pipeline Stage of Execution: Pre Stage


Execution Mode: Synchronous



Triggering Pipeline: Child Pipeline



Message: Update


Primary Entity: contact


Filtering Attribute: birthdate


Eventing Pipeline Stage of Execution: Pre Stage


Execution Mode: Synchronous



Triggering Pipeline: Child Pipeline



Summary



That’s all there is to it! The users will now be able to use Advanced Find to quickly identify their contacts birthday in a certain time period from now on. For the existing contacts previously stored in CRM, you will need to write a one-time SQL script to update the birthday fields in the MSCRM database in order for CRM to return the correct data back to the users. Hopefully this will help you on your next CRM project.



clip_image004



clip_image006



Cheers,



Darren Liu

CRM 4.0 Build Versions

Build Number Released Details
04.00.7333.2138 10/22/2009 Update Rollup 7
4.0.7333.1750 8/26/2009 Rollup Update 6
4.0.7333.1676 7/8/2009 Mobile Express +Rollup 5
4.0.7333.1644 7/2/2009 Rollup Update 5
4.0.7333.1551 5/7/2009 Rollup Update 4
4.0.7333.1408 3/12/2009 Update Rollup 3
4.0.7333.1316 2/8/2009 Rollup Update #2 (Re-Release)
4.0.7333.1312 1/15/2009 Rollup Update #2 (Original Release)
4.0.7333.1113 11/24/2008 Rollup Update #1
4.0.7333.3 12/19/2007 RTM
4.0.7333.2 Dec-07 RC2 (Internal)
4.0.7309.0 Nov-07 RC0 (Limited Release)
4.0.7219.10 Aug-07 Beta - CTP3
4.0.7044.22 May-07 Beta - CTP2
4.0.6319.16 October 2006 (?) Beta - CTP1

Improving Microsoft Dynamics CRM Performance and Securing Data with Microsoft SQL Server 2008

Microsoft SQL Server® 2008 contains a variety of features that, when implemented properly, can improve the performance of a Microsoft Dynamics® CRM 4.0 implementation and secure the data within that deployment. These Microsoft SQL Server 2008 features include: - Compression - Sparse Columns - Transparent Data Encryption - Backup Compression The MS CRM E2 team, working in conjunction with the Microsoft SQL Server team, recently completed a project that was designed to: 1. Evaluate the new scenarios that these Microsoft SQL Server 2008 features expose 2. Measure the performance impact of implementing these features, both singly and in selected combinations This paper provides an overview of these Microsoft SQL Server 2008 features, together with benchmark results and recommendations for implementation.

 

Click here

Create Activities using the Dynamic Entity Way

Friday, December 19, 2008 Darren's CRM Blog


I haven't touch CRM SDK for a while since I am working on another project not directly related to CRM. One of my old client required us to populate CRM with some more training data so they can use it for their training. So I have to modify the training processor that my teammates wrote to add activities to CRM. It appears to me that everything in the training processor have used Dynamic Entity for create, update, and delete.

To create an activities using dynamic entity is pretty straight forward, however I got stuck when I have to deal with the sender and recipient fields on a phone call, email, appointment and fax activity. Sender and Recipient field are ActivityParty type, I have done some research online and I was not able to find a way to associate the two fields to an activity using the dynamic approach. After going through the SDK and I was able to figure it out. I would like to share it since you might have to do the same in your next project.

Method 1: Not using Dynamic Entity

activityparty actParty = new activityparty();
actParty.partyid = new Lookup();
actParty.partyid.Value = new Guid("ENTER CONTACT GUID");
actParty.partyid.type = "contact";

activityparty actParty2 = new activityparty();
actParty2.partyid = new Lookup();
actParty2.partyid.Value = new Guid("ENTER USER GUID");
actParty2.partyid.type = "systemuser";

phonecall call = new phonecall();
call.from = new activityparty[] { actParty };
call.to = new activityparty[] { actParty2 };
call.description = "Test";

crmService.Create(call);


Method 2: Using Dynamic Entity



Property subject = new StringProperty();
((StringProperty)subject).Name = "subject";
((StringProperty)subject).Value = "Test";

Property description = new StringProperty();
((StringProperty)description).Name = "description";
((StringProperty)description).Value = "Test";

// Create From:
Property party1 = new LookupProperty();
((LookupProperty)party1).Name = "partyid";
((LookupProperty)party1).Value = new Lookup();
((LookupProperty)party1).Value.type = "contact";
((LookupProperty)party1).Value.Value = new Guid("ENTER CONTACT GUID");

DynamicEntity actParty1 = new DynamicEntity();
actParty1.Name = "activityparty";
actParty1.Properties = new Property[] { party1 };

DynamicEntityArrayProperty from = new DynamicEntityArrayProperty();
((DynamicEntityArrayProperty)from).Name = "from";
((DynamicEntityArrayProperty)from).Value = new DynamicEntity[] { actParty1 };

// Create To:
Property party2 = new LookupProperty();
((LookupProperty)party2).Name = "partyid";
((LookupProperty)party2).Value = new Lookup();
((LookupProperty)party2).Value.type = "systemuser";
((LookupProperty)party2).Value.Value = new Guid("ENTER USER GUID");

DynamicEntity actParty2 = new DynamicEntity();
actParty2.Name = "activityparty";
actParty2.Properties = new Property[] { party2 };

DynamicEntityArrayProperty to = new DynamicEntityArrayProperty();
((DynamicEntityArrayProperty)to).Name = "to";
((DynamicEntityArrayProperty)to).Value = new DynamicEntity[] { actParty2 };

 

// Create Phone Call Activity:
DynamicEntity activity = new DynamicEntity();
activity.Name = EntityName.phonecall.ToString();
activity.Properties = new Property[]{subject, description, from, to};

TargetCreateDynamic target = new TargetCreateDynamic();
target.Entity = activity;

CreateRequest request = new CreateRequest();
request.Target = target;

CreateResponse response = (CreateResponse)crmService.Execute(request);



That's it! Hope this will help you in your next project! :)

CRM 4.0 List Web Part Available!

CRM 4.0 List Web Part is available to download today. The list web part supports Multi-tenancy, IFD, 64bit and many more new enhancements comparing to the previous release.

System Requirement:

  • Windows Server 2003 or Windows Server 2008
  • Microsoft Dynamics® CRM 4.0
  • Microsoft Windows® SharePoint® Services 3.0 SP1
  • Microsoft® Office SharePoint® Server (MOSS) 2007 SP1
  • Microsoft® Internet Explorer 6 with SP1 or later versions

To download the list web part, click on the link below.

http://www.microsoft.com/downloads/details.aspx?FamilyID=3b6eb884-ec15-4288-a2a3-d0b47e057458&DisplayLang=en

Close Opportunity via SDK

Posted by Darren Liu at 11:19 AM

To close a CRM opportunity is different comparing to other CRM entities. If you want to close an opportunity, you need to use the WinOpportunityRequest and LostOpportunityRequest in the CRM SDK instead of the SetState requests. The code snippet below simply shows you how to set an opportunity to Win status via the CRM SDK.

opportunityclose close = new opportunityclose();
close.opportunityid = new Lookup();
close.opportunityid.Value = targetOppId;

WinOpportunityRequest request = new WinOpportunityRequest();
request.OpportunityClose = close;
// Update the status code according to your environment
request.Status = 1;

crmService.Execute(request);

Example Of Deactivating An Entity

by Danny Varghese 03.06.09

One of the least published example of CRM code is deactivating an entity, probably because it's not used as often as creating, updating or retrieving entities. Below is an example I've used on several occasions to deactivate an entity:

   1:  



   2: public void DeactivateEntity(Guid entityId)



   3: {



   4: //variable initialization



   5: SetStateDynamicEntityRequest deactivateReq = new 



   6: SetStateDynamicEntityRequest();



   7: //deactivate the cloned assignment



   8: deactivateReq = new SetStateDynamicEntityRequest();



   9: deactivateReq.State = "Inactive";



  10: deactivateReq.Status = 2;



  11: deactivateReq.Entity = new Moniker();



  12: deactivateReq.Entity.Name = <entity name>



  13: deactivateReq.Entity.Id = entityId;



  14: //execute the deactivation request



  15: service.Execute(deactivateReq);



  16: }