Nov 21, 2012

Recursive workflows instead of windows services?

Please refer this for better solution.

In Dynamics CRM, we don’t have a facility to schedule an activity. Typically, one might need to change the status of a record without any interaction/ trigger. For example expiration of insurance policy. For this what we usually do is writing a windows service.

http://crmbusiness.wordpress.com/2011/05/24/crm-2011-how-to-schedule-recurring-workflows-in-crm-2011/

This blog article encourages us to use a recursive workflow instead of a windows service. It is a clever way of writing a workflow in a recursive pattern with delays to accomplish the objective. It seems fantastic since it can be achieved without any trouble or coding. I did a test workflow as this author explains (with a waiting time of 1 hour) and it worked well for me. 

Anyway, it is yet to be taken to the discussion table to check positive and negative consequences.

Also I think, it is better to do the state change like simple operation through the workflow and triggers a plug-in for rest of the complex operations if the requirement consists of lengthy logics.
Furthermore, we can even identify this call by filtering by asynchronous call filter as below.

if (context.CallerOrigin.GetType() == 
            typeof(Microsoft.Crm.Sdk.AsyncServiceOrigin))
        {
            //plug-in steps
        }

Nov 11, 2012

Importing CRM instance from different domain

Importing a CRM instance can be quite tricky. Typically, we might need to get an identical instance from production server to a new developing server or wise versa.

I am explaining the steps with illustrations. This worked for me. As I see, we have three main tasks to be done. They are getting the backup from the existing database; restore it in new server and configuring the CRM using Deployment manager.

1) Getting the backup from the existing database

There is nothing new about this step rather than getting the full back up of the organization which is in the format of <NAME>_ MSCRM. Right click the db >tasks>Back up take you to the wizard. Under option I usually select below options;
 a) Override all existing backup sets
 b) Verify backup when finished
 c) Perform checksum before writing to media

2) Restore the database in new (destination) server
Right click any database> task>restore>database takes you to the wizard. Then change the database name as required in the format of <NAME>_ MSCRM, where NAME will be the name of new CRM instance. Then go to “From device” and browse to the database backup taken in the previous task.


3) Import/configure  the CRM instance

a. Go to Organizations node, right click the  select “Import Organization”, which will return below window with newly created database.


b. Give the name in both places


c. Specify the URL of reporting server for the instance and proceed.


d. When it comes to the user mapping window, select “Automatially map users” option and proceed.


e. Then you will probably get below error message.


Press Ok, you will get below window.


f. Now find the “System Administrator” from existing user column and assign it to yourself by licking the browse button.



If you forget to do this you will be thrown another error message like below one.


g. If you have done everything correctly, you will now see below window.


h. When you proceed, you will see below kind of summery.


i. Now you are ready with new instance.


Now you are ready to work with new instance.

However, keep in mind; you may need to take below steps depending on the customizations done in your system.

1) If you have any kind of configuration files, you need to copy and change as required.
2) If you have done Plug-ins you must copy those DLL files to Program Files\Microsoft Dynamics CRM\Server\bin\assembly
(Open the plug-in registration tool and notice your plug-ins are already registered correctly)
3) Add other users of domain your new CRM is placed.

Nov 1, 2012

Sample Plug-in: Delete

It is important to do something, when a record is being deleted. For that we need to use a plug-in that catches the pre-delete action.

Difference of this approach is we retrieve entity reference instead of entity. Then we can retrieve the other attributes through retrieve method since we got the Id. (While we are in Pre stage we still have time to grab them.)

Check the code as below;

using System;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System.ServiceModel;

namespace TestCompany.CRM.Plugin
{
 public class officePreDelete : IPlugin
 {
   public void Execute(IServiceProvider serviceProvider)
   {
     IPluginExecutionContext context;
     IOrganizationServiceFactory factory;
     IOrganizationService service;

     try
     {
       context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
       if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)
       {
         EntityReference EntityRef = (EntityReference)context.InputParameters["Target"];
         if (EntityRef.LogicalName != "new_office")
             return;
                     
         factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
         service = factory.CreateOrganizationService(context.UserId);
                   
         // Do the logic as required
         // use EntityRef.Id retrive other attributes

        }
      }
      catch (FaultException<OrganizationServiceFault> e)
      {
        throw e;
      }
      finally
      {
        service = null;
        factory = null;
        context = null;
      }
   }
 }
}

Now check the plug-in registration setting;

 
Important Note
Pl note, though we are in pre-Delete stage, record has already lost the relationships with other records. This means you are not able to query other records using the values in deleting record. If you need to do, what needs to do is register the plug-in step in Pre-validation stage than Pre-operation.
 
Related posts;
Sample Plug-in: Compare Pre and Post images on Update
Sample Plug-in code: Create and Update
Retrieve attributes of entity object