Friday 24 May 2013

Using Child Workflows in MS CRM 2011.

While working with the Projects we have to implement several logic as per the Client Need.

Here is the requirement.

1)Case Severity can be (1,2,3,4) Where 1 is the highest and 4 is the lowest.
2)Whenever Severity is raised to 1.It should trigger a mail to an user and keep on sending until Status of the Case is Closed.

Solution:

1)"Keep on sending until Status of the Case is Closed" this Can be achieved using child workflow.
2)"Whenever severity is raised to 1" :It means we should compare the previous severity with the new severity.

Note:
So we should Create  a custom field "previous severity".Set this field  with the value of case severity.When the Case is Created.You can achieve this using either workflow or JavaScript.

Creating Workflows:We will create two workflows

1)Main Workflow
2)Child workflow

Main workflow will call the child workflow and child workflow will call itself to achieve this.

Main Workflow Screen shot:



Child Workflow Screen shot:













Note : This workflow is on change of "Severity" of case.

Hope this helps,

Regards,

Yusuf

Clone an Opportunity in MS CRM 2011 by Plugin.

Below is a Plugin to create an Opportunity Clone [Cloning opportunity products as well].It uses early bound approach.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Crm.Sdk.Messages;
using Entities = Pes.My.Configurations.Entities;
using System.ServiceModel;
using Pes.My.Configurations.Entities;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Client;
 
namespace My.Crm.Plugins.Opportunity
{
    public class PostUpdate : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            Entities.Opportunity oppRec;
 
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
 
            // This plug-in was fired from the playback queue after the user selected to go online within Microsoft Dynamics CRM for Outlook.
            if (context.IsExecutingOffline || context.Depth > 1)
                return;
 
 
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"is Entity)
            {
 
                //Verify that the entity represents an Opportunity
                if (((Entity)context.InputParameters["Target"]).LogicalName != Pes.My.Configurations.Entities.Opportunity.EntityLogicalName || context.MessageName != "Update")
                    return;
                else
                    oppRec = ((Entity)context.InputParameters["Target"]).ToEntity<Pes.My.Configurations.Entities.Opportunity>();
            }
            else
            {
                return;
            }
 
            try
            {
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
 
 
                using (var MyContext = new MyContext(service))
                {
 
                    if (oppRec.My_IsCloned == true)
                    {
                        if (context.Depth == 1)
                        {
 
                            Entity opportunity = null;
 
                            opportunity = service.Retrieve(Entities.Opportunity.EntityLogicalName, oppRec.Id, new ColumnSet(true));
 
                            Entity cloneopportunity = new Entity();
 
                            opportunity.Attributes.Remove("opportunityid");
                            opportunity.Id = Guid.NewGuid();
 
                            cloneopportunity = opportunity;
                            Guid ClonedOppId = service.Create(cloneopportunity);
 
 
                            List<Entities.OpportunityProduct> listoppproduct = MyContext.OpportunityProductSet
                                      .Where(acp => acp.OpportunityId.Id == oppRec.Id).ToList<Entities.OpportunityProduct>();
                            foreach (OpportunityProduct objoppproduct in listoppproduct)
                            {
                                cloneOppProduct((Guid)objoppproduct.Id, ClonedOppId, service);
                            }
 
 
                        }
 
                    }
 
                }
 
 
            }
            catch (InvalidPluginExecutionException)
            {
                throw;
            }
            catch (FaultException<OrganizationServiceFault> ex)
            {
                throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
            }
 
        }
 
        private void cloneOppProduct(Guid guid, Guid Opp, IOrganizationService service)
        {
 
            Entity opportunityproduct = null;
            opportunityproduct = service.Retrieve(Entities.OpportunityProduct.EntityLogicalName, guid, new ColumnSet(true));
 
            Entity cloneopportunityproduct = new Entity();
 
            opportunityproduct.Attributes.Remove("opportunityproductid");
            opportunityproduct.Attributes.Remove("opportunityid");
            opportunityproduct.Id = Guid.NewGuid();
            opportunityproduct.Attributes["opportunityid"] = new EntityReference(Entities.Opportunity.EntityLogicalName, Opp);
            cloneopportunityproduct = opportunityproduct;
            service.Create(cloneopportunityproduct);
 
        }
    }
}



Note: I run this plugin from ribbon button "Clone Opportunity".Here I am setting Custom field "My_IsCloned " to true and saving the form using javaScript.And On post update it triggers this plugin.


Also you have to create an early bound class using CrmSvcUtil  below is an example

CrmSvcUtil.exe /out:MyEntities.cs /url:https://Mydev1.api.crm.dynamics.com/XRMServices/2011/Organization.svc /username:name@My.com /password:pass123 /namespace:Pes.My.Configurations.Entities /serviceContextName:MyContext 

Use the class generated i.e MyEntities [here] in your project and accomplish the same.

Hope this helps.

Yusuf

Custom Workflow Activity not appearing in MS CRM 2011 Issue.

I created a Custom Workflow activity and deployed it in Development server.It was working correct .I deployed same assembly in Staging server and I was surprised to see that assembly was  not showing the workflow which I added. Although It was shown in plugin registration tool.

Solution 1: Problem was in Strong name key.I created a different Strong name key and updated the  Custom workflow assembly.I unregistered the old assembly and registered the updated one.
It worked like a  Charm.

Solution 2: As suggested by Philip Update the AssemblyVersion and AssemblyFileVersion.
check  below link
http://blog.philipverlinden.be/crm/newly-added-custom-workflow-activity-not-showing-when-adding-a-new-step/


Hope this helps.

Friday 17 May 2013

Querying OptionSetValue from MS CRM using Linq query with join operation

Below Code is taken from this post ,
   
        private string GetPickListText(string entityName, string attributeName, int optionSetValue)
        {
            string AttributeName = attributeName;
            string EntityLogicalName = entityName;

            RetrieveEntityRequest retrieveBankAccountEntityRequest = new RetrieveEntityRequest
            {
                EntityFilters = EntityFilters.All,
                LogicalName = EntityLogicalName
            };
            RetrieveEntityResponse retrieveBankAccountEntityResponse = (RetrieveEntityResponse)_serviceContext.Execute(retrieveBankAccountEntityRequest);
            Microsoft.Xrm.Sdk.Metadata.EntityMetadata metadata = retrieveBankAccountEntityResponse.EntityMetadata;
            Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata picklistMetadata = metadata.Attributes.FirstOrDefault(attribute => String.Equals(attribute.LogicalName, attributeName, StringComparison.OrdinalIgnoreCase)) as Microsoft.Xrm.Sdk.Metadata.PicklistAttributeMetadata;
            Microsoft.Xrm.Sdk.Metadata.OptionSetMetadata options = picklistMetadata.OptionSet;

            IList<OptionMetadata> picklistOption = (from o in options.Options
                                                    where o.Value.Value == optionSetValue
                                                    select o).ToList();

            string picklistLabel = (picklistOption.First()).Label.UserLocalizedLabel.Label;
            return picklistLabel;
        }



Hope this helps,

Yusuf