Thursday 12 December 2013

Get the record ID from the URL

As a developer, you will find yourself extracting record ID from the URL.Most of the time we open the notepad and using our  ID extracting skills we strip out the ID from the URL.To make this task more easier just use URL Decoder/Encoder


1. Copy and paste your URL in the textbox
2. Press Decode button two times.
3.Your URL is decoded you can easily copy the ID.



Hope this helps.

Wednesday 14 August 2013

Showing only selected Tab on the MS CRM 2011 Form

When you open any form it loads all the tabs on the form.Suppose you want to display the selected tab on the form at a time.Here is a JavaScript function to hide the other tabs.This function can be called on the Form OnLoad and TabStateChange events.

1.JavaScript Function:

function ToggleTabDisplayState(name) {
 
    var currentTab = Xrm.Page.ui.tabs.get(name);
    if (currentTab != null && currentTab.getDisplayState() == "expanded") {
        var currentTabId = currentTab._control.get_id();
        var tabs = Xrm.Page.ui.tabs.get();
        for (var i in tabs) {
            var tab = tabs[i];
            var tabId = tab._control.get_id();
            if (tabId != currentTabId) {
                if (tab.getDisplayState() == "expanded") {
                    tab.setDisplayState("collapsed");
                }
                document.getElementById(tabId).style.display = "none";
            }
        }
    }
}
2.Before Calling the Function :
Form shows all the tabs before calling the above function Form OnLoad event.
 
 
 
 3.Calling the Function :
 
3.1 Call on Form OnLoad event :
 
Suppose on Form OnLoad event I want to show only "General" tab and hide other tabs then call the above function as below.
 
function Form_OnLoad() {
    ToggleTabDisplayState("general"); //"general" is the name of the tab
}
 
3.2 Call on TabStateChange event:
 
Call the same function on the TabStateChange event 
 
Go to Form Properties =>Select Control as tab name=>Add Handler =>Select Library=>add function as ToggleTabDisplayState =>Provide name of the tab in Comma separated parameters list for example 
"contacts" => Save and publish


4.After Calling the Function :
Form shows only selected tab after calling the above function Form OnLoad event.
 
 










Hope it helps,
Regards,
Yusuf



Tuesday 16 July 2013

Retrieving Subgrid Items count using Javascipt in MS CRM 2011/MS CRM 2013

Retrieving Subgrid Items count using Javascipt.

1.Get the subgrid  using "Name" of subgrid as given below.
















2.Write the Javascript function as given below:

function subgridItemCount() {
 
      // Get the Subgrid Control
    var grid = Xrm.Page.ui.controls.get('LineItems')._control;
    if (grid.get_innerControl() == null) {
        setTimeout(subgridItemCount, 1000);
        return false;
    }
    else if (grid.get_innerControl()._element.innerText.search("Loading") != -1) {
        setTimeout(subgridItemCount, 1000);
        return false;
    }
    var countRec = grid.get_innerControl().get_allRecordIds().length;
    if (countRec > 0) {
        alert(countRec);
 
    }
 
}


For MS CRM 2013:

function FindControl() {
    if (document.getElementById('subgridName')!= null) {
        var count=document.getElementById('subgridName').control.get_totalRecordCount();
        alert(count);
        }
        else {
            setTimeout("FindControl()", 1000);
        }
    }


3.Result




























Hope this helps,

Regards,

Yusuf

Tuesday 2 July 2013

Retrieve N:N records in MS CRM 2011

Retrieving N:N records in MS CRM 2011 using LINQ requires less code and is straightforward.

I am assuming that "Account" is in N:N relationship with "Custom Entity".

Below is the screenshot for relationship





















Here is the Screenshot of account having custom entity records





























Query:

LINQ query to get all the N:N custom entity records for the above Account.

 string accountId = "CC572EC9-01E3-E211-AC62-984BE173A384";
  var customEntities = (from NtoN in makeUseOfContext.new_customentity_accountSet
                        where NtoN.accountid.Value == new Guid(accountId) && 
                        NtoN.new_customentityid != null
                         select new { 
                                    customentityid = NtoN.new_customentityid.Value 
                                   }).ToList();
        
Debug Mode:

















Similarly we can get the Accounts associated to the custom  entity.
Hope it will help someone somewhere :)

Thanks,
Yusuf

Microsoft Dynamics CRM - Orion release

The next major release of Microsoft Dynamics CRM will come in the form of the Orion release in the second half of 2013.

Major Changes:
.
The major themes for the Orion release are as follows:
• User Experience – Continuation of the journey in Polaris
• Ubiquitous – Role-tailored applications for Sales Professionals. (Ubiquitous key word replaces the word Mobile. You will be hearing this a lot more).
• Productivity – Internal Collaboration for the on-premise customers & Server Sync enhancements
• Business Process – Process-centric theme continued to the next level
• Online – Online first focus to continue (this means CRM Online will get all the new features first before OnPremise)

Orion User Interface:

Firstly, you will notice it has no ribbon. Next it has no left navigation bar. The navigation bar is now at the top (as shown in purple colour in the screenshot below).



Here is the full post.Refer this too.



Regards,

Yusuf

Friday 21 June 2013

CRM 2011 – New SDK version 5.0.16 available

The MS CRM Team have released an updated CRM 2011 SDK version 5.0.16 which can be downloaded here http://www.microsoft.com/en-us/download/details.aspx?id=24004 or viewed on MSDN here http://msdn.microsoft.com/en-us/library/gg309408.aspx Check out the SDK Release History notes herehttp://msdn.microsoft.com/en-us/library/dn198205.aspx

Now the common question here is that what is changing in the new version.There are some changes please go through below post on

MSCRM Bing’d




Regards,
Yusuf

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


Wednesday 30 January 2013

Clone a record in MS CRM 2011

Sometime in CRM there is a need to copy the existing record.For example there may be a need to clone the existing case so that service representative can update some fields on the cloned case.

Q.How can we achieve it in MS CRM 2011
A. It can be achieved either by JavaScript or Plugin.

We will try to achieve with JavaScript using "Relationships" mappings feature in MS CRM 2011.

Q:What we need to do?
  
1)Add a ribbon button called "Clone Case"
2)Creating a 1:N relationship with Case to Case then generating mappings.
3)On button click Open the URL of the cloned Case.


Implementation:

1)Add a ribbon button called "Clone Case"

Add a ribbon button called "Clone Case".You can use ribbon workbech for this on click of this button it will call a Javascript function called "cloneCase" in "My_CustomRibbonJavascript" webresource.
Or you can do manually like.

1)Create a solution add "Case" entity to it.
2)Export the Solution.
3)Extract the Solution.
4)Open Customizations.xml in Visual studio.
5)Replace <RibbonDiffXmlwith the below given XML
6)Take care of adding the icons as given in below XML in CRM as webresources before import.

<RibbonDiffXml>
  <CustomActions>
 
    <CustomAction Id="My.MSCRM.incident.form.Clone.Button.CustomAction" Location="Mscrm.Form.incident.MainTab.Collaborate.Controls._children" Sequence="0">
      <CommandUIDefinition>
        <Button Command="MSCRM.incident.form.Clone.Command" Id="MSCRM.incident.form.Clone.Button" Image32by32="$webresource:My_Clone32" Image16by16="$webresource:My_Clone16" LabelText="$LocLabels:MSCRM.incident.form.Clone.Button.LabelText" Sequence="0" TemplateAlias="o1" ToolTipTitle="$LocLabels:MSCRM.incident.form.Clone.Button.ToolTipTitle" ToolTipDescription="$LocLabels:MSCRM.incident.form.Clone.Button.ToolTipDescription" />
      </CommandUIDefinition>
    </CustomAction>
 
  </CustomActions>
  <Templates>
    <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
  </Templates>
  <CommandDefinitions>
 
    <CommandDefinition Id="MSCRM.incident.form.Clone.Command">
      <EnableRules/>
      <DisplayRules>
        <DisplayRule Id="MSCRM.incident.form.Clone.DisplayRule" />
      </DisplayRules>
      <Actions>
        <JavaScriptFunction FunctionName="cloneCase" Library="$webresource:My_CustomRibbonJavascript" />
      </Actions>
    </CommandDefinition>
 
  </CommandDefinitions>
  <RuleDefinitions>
    <TabDisplayRules />
    <DisplayRules>
 
      <DisplayRule Id="MSCRM.incident.form.Clone.DisplayRule">
        <FormStateRule State="Create" InvertResult="true" />
      </DisplayRule>
 
    </DisplayRules>
    <EnableRules/>
 
  </RuleDefinitions>
  <LocLabels>
 
    <LocLabel Id="MSCRM.incident.form.Clone.Button.LabelText">
      <Titles>
        <Title description="Clone Case" languagecode="1033" />
      </Titles>
    </LocLabel>
    <LocLabel Id="MSCRM.incident.form.Clone.Button.ToolTipDescription">
      <Titles>
        <Title description="Clone Case" languagecode="1033" />
      </Titles>
    </LocLabel>
    <LocLabel Id="MSCRM.incident.form.Clone.Button.ToolTipTitle">
      <Titles>
        <Title description="Clone Case" languagecode="1033" />
      </Titles>
    </LocLabel>
 
  </LocLabels>
</RibbonDiffXml>

2)Creating a 1:N relationship with Case to Case then generating mappings.

Open the Case enity relationship(1:N) and Create a relationship with Case.Open the created relationship and generate mappings.

Refer below screenshots











3)On button click Open the URL of the cloned Case.

Add a new webresource called "My_CustomRibbonJavascript" add the  "cloneCase" function to it


function GetContext() {
    var _context = null;
    if (typeof GetGlobalContext != "undefined")
        _context = GetGlobalContext();
    else if (typeof Xrm != "undefined")
        _context = Xrm.Page.context;
    return _context
}
function cloneCase() {
 
    if (Xrm.Page.data.entity.getId() == null) {
        alert('First save the record before Clone Case')
 
    }
    else {
        var CRMContext = GetContext();
        var serverUrl = CRMContext.getServerUrl();
        var caseid = Xrm.Page.data.entity.getId();
        caseid = caseid.replace('{''').replace('}''');
 
        //Below URL is for CRM online  
        var url = serverUrl + 'main.aspx?etc=112&extraqs=%3f_CreateFromId%3d%257b' + caseid + '%257d%26_CreateFromType%3d112%26etc%3d112%26pagemode%3diframe&pagetype=entityrecord';
 
        openNewWindow(url, 900, 600, 'toolbar=no,menubar=no,resizable=yes');
    }
 
 
}


Note:How to create the URL

Since Case is in 1:N relationship It will appear in case left navigation pane.Click on Case button and add the new Case.Copy the created URL and make it dynamic.

For Onpresmise MS CRM 2011 URL will be like this

var url = serverUrl + '/cs/cases/edit.aspx?_CreateFromType=112&_CreateFromId=' +
 Xrm.Page.data.entity.getId();



 Hope it helps someone somewhere :)

Regards,

Yusuf



Friday 11 January 2013

A Scenery

I spent two years in Kerala (India) for studies.I am very much impressed by the natural beauty of Kerala.I feel that in Kerala everywhere there is an opportunity to see the Scenery.


CRM 2011: Ribbon not loading in Mozilla Firefox and Chrome

Good news for MS CRM 2011 developer is that December 2012 Service Update for Microsoft Dynamics CRM 2011 (Polaris) will allows cross browser compatibility and some other splendid updates.

Now the chances for Javascipt errors will be more across different browsers.Now onwards we have to more careful while writing JavaScript Code.We need to make sure it will work different across other browsers besides IE as well.

We are working on Polaris CRM 2011 and customizing using Javascript.While testing functionality we came to know that Case ribbon is not being loaded.

Here comes the  Microsoft Dynamics CRM 2011 Custom Code Validation Tool  into picture.

What is it :"Custom Code Validation Tool to ensure their existing customizations will work with the next service release of CRM 2011, code named Polaris"

For more information read this blog.



After running this tool on Case JavaScript I got the erroneous code (marked in blue colour) which was causing the issue for the ribbon loading.I updated the JavaScript to fix that.

It's now working fine.Below is the screenshot of MS CRM 2011 running in Mozilla Firefox.



Hope it helps someone.

Regards,
Yusuf

Wednesday 9 January 2013

Speaking Lines !!!

Some time lines says more than words.Lines may be beautiful  if drawn meaningfully.
Enjoy the "Speaking Lines" drawn by me :)


Tuesday 8 January 2013

Override the Resolve Case System ribbon button functionality?



When you resolve a Case a pop up appears where you can provide some details regarding closing the Case.Here I will show how can  we overwrite the default functionality of the Resolve Case.


When you resolve a case it creates an case resolution activity.Which we need to take care while overwriting the default functionality.


Customization Aim:
To remove the "Resolve Case" dialog  box and change the name of the Resolve Case to 'Close Case'.

What to do ?:What things needs to be customized in order to achieve this.


1)We need to customize the ribbon definition of Case entity i.e  RibbonDiffXml.
2)We need to create one custom field on Case entity.
3)We need to write a JavaScript function.
4)We have to write a plugin which will take care of resolving the Case.

Note:
Case can be resolved from 'Form' level and 'HomePage grid'.We will take care of both the scenarios.


1.Customizing the Case ribbon button(HomePage grid and  Form):

1.1) Create a solution containing Case entity.Export it and save it.Extract the solution file.
        Open the "customizations.xml" search the <RibbonDiffXml> tag.
        Replace this with the following


<RibbonDiffXml>
        <CustomActions>
 
          <CustomAction Id="new.Mscrm.Form.incident.Resolve.CustomAction" Location="Mscrm.Form.incident.MainTab.Actions.Controls._children" Sequence="3">
            <CommandUIDefinition>
              <Button Alt="$Resources:Ribbon.Form.incident.MainTab.Actions.Resolve" Command="Mscrm.Form.incident.Resolve" Id="Mscrm.Form.incident.Resolve" Image32by32="/_imgs/ribbon/resolvecase32.png" Image16by16="/_imgs/ribbon/ResolveCase_16.png" LabelText="$LocLabels:Mscrm.Form.incident.Resolve.LabelText" Sequence="3" TemplateAlias="o1" ToolTipTitle="$Resources:Ribbon.Form.incident.MainTab.Actions.Resolve" ToolTipDescription="$Resources:Ribbon.Tooltip.ResolveCase" />
            </CommandUIDefinition>
          </CustomAction>
 
 
          <CustomAction Id="new.Mscrm.HomepageGrid.incident.Resolve.CustomAction" Location="Mscrm.HomepageGrid.incident.MainTab.Actions.Controls._children" Sequence="3">
            <CommandUIDefinition>
              <Button Alt="$Resources:Ribbon.Form.incident.MainTab.Actions.Resolve" Command="Mscrm.HomepageGrid.incident.Resolve" Id="Mscrm.HomepageGrid.incident.Resolve" Image32by32="/_imgs/ribbon/resolvecase32.png" Image16by16="/_imgs/ribbon/ResolveCase_16.png" LabelText="$LocLabels:Mscrm.HomepageGrid.incident.Resolve.LabelText" Sequence="3" TemplateAlias="o1" ToolTipTitle="$Resources:Ribbon.Form.incident.MainTab.Actions.Resolve" ToolTipDescription="$Resources:Ribbon.Tooltip.ResolveCase" />
            </CommandUIDefinition>
          </CustomAction>
 
        </CustomActions>
        <Templates>
          <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
        </Templates>
        <CommandDefinitions>
          <CommandDefinition Id="Mscrm.Form.incident.Resolve">
            <EnableRules>
              <EnableRule Id="Mscrm.CanChangeIncidentForm" />
            </EnableRules>
            <DisplayRules>
              <DisplayRule Id="Mscrm.CanChangeIncidentForm" />
              <DisplayRule Id="Mscrm.IncidentIsActive" />
            </DisplayRules>
            <Actions>
              <JavaScriptFunction FunctionName="resolveCase" Library="$webresource:new_CustomRibbonJavascript" />
            </Actions>
          </CommandDefinition>
          <CommandDefinition Id="Mscrm.HomepageGrid.incident.Resolve">
            <EnableRules>
              <EnableRule Id="Mscrm.SelectionCountExactlyOne" />
              <EnableRule Id="Mscrm.VisualizationPaneNotMaximized" />
            </EnableRules>
            <DisplayRules>
              <DisplayRule Id="Mscrm.CanChangeIncidentForm" />
            </DisplayRules>
            <Actions>
              <JavaScriptFunction FunctionName="resolveCaseFromGrid" Library="$webresource:new_CustomRibbonJavascript">
                <CrmParameter Value="SelectedControlSelectedItemIds" />
              </JavaScriptFunction>
            </Actions>
          </CommandDefinition>
 
        </CommandDefinitions>
        <RuleDefinitions>
          <TabDisplayRules />
          <DisplayRules>
 
            <DisplayRule Id="Mscrm.CanChangeIncidentForm">
              <EntityPrivilegeRule EntityName="incident" PrivilegeType="Write" PrivilegeDepth="Basic" />
              <EntityPrivilegeRule EntityName="incident" PrivilegeType="AppendTo" PrivilegeDepth="Basic" />
              <EntityPrivilegeRule EntityName="activitypointer" PrivilegeType="Create" PrivilegeDepth="Basic" />
              <EntityPrivilegeRule EntityName="activitypointer" PrivilegeType="Append" PrivilegeDepth="Basic" />
            </DisplayRule>
 
            <DisplayRule Id="Mscrm.IncidentIsActive">
              <FormStateRule State="Existing" />
            </DisplayRule>
 
          </DisplayRules>
          <EnableRules>
 
            <EnableRule Id="Mscrm.CanChangeIncidentForm">
              <FormStateRule State="Create" InvertResult="true" />
              <RecordPrivilegeRule PrivilegeType="Write" AppliesTo="PrimaryEntity" />
              <RecordPrivilegeRule PrivilegeType="AppendTo" AppliesTo="PrimaryEntity" />
            </EnableRule>
 
            <EnableRule Id="Mscrm.SelectionCountExactlyOne">
              <SelectionCountRule AppliesTo="SelectedEntity" Minimum="1" Maximum="1" />
            </EnableRule>
            <EnableRule Id="Mscrm.VisualizationPaneNotMaximized">
              <CustomRule FunctionName="Mscrm.RibbonActions.disableButtonsWhenChartMaximized" Library="/_static/_common/scripts/RibbonActions.js">
                <CrmParameter Value="SelectedControl" />
              </CustomRule>
            </EnableRule>
          </EnableRules>
        </RuleDefinitions>
        <LocLabels>
          <LocLabel Id="Mscrm.Form.incident.Resolve.LabelText">
            <Titles>
              <Title description="Close Case" languagecode="1033" />
            </Titles>
          </LocLabel>
          <LocLabel Id="Mscrm.HomepageGrid.incident.Resolve.LabelText">
            <Titles>
              <Title description="Close Case" languagecode="1033" />
            </Titles>
          </LocLabel>
 
        </LocLabels>
      </RibbonDiffXml>


2.Case form Customization:

Customize the Case entity create one radio button with logical name "new_iscaseresolved" having default value false.Hide this field on the form.We will make use of this field for writing our logic.


3.Write the Javascipt function:

Create a webresource  called "new_CustomRibbonJavascriptand add the following JavaScript functions to it.


function resolveCase() {
    try {
        var answer = confirm("Do you want to Close the Case?")
        if (answer) {
 
            Xrm.Page.getAttribute("new_iscaseresolved").setValue(true);
            Xrm.Page.data.entity.save();
 
        }
    }
    catch (err) { }
}
 
function resolveCaseFromGrid(CaseIdList) {
 
    try {
        if (CaseIdList != null) {
            var caseid = CaseIdList[0]
            caseid = caseid.replace('{''').replace('}''');
            var answer = confirm("Do you want to Close the Case?")
            if (answer) {
                if (checkCaseOpenActivities(caseid)) {
                    var ChangesToUpdate = {
                        new_IsCaseResolved: true
                    };
 
                    updateRecord(caseid, ChangesToUpdate, "IncidentSet");
 
 
                }
 
                else {
 
                    alert('Please close open activities before closing the Case');
                }
            }
        }
 
    }
    catch (err) { }
}
 
 
function checkCaseOpenActivities(caseId) {
    var ODataSelect = "ActivityPointerSet?$select=ActivityId&$filter=RegardingObjectId/Id eq guid'" + caseId + "' and StateCode/Value eq 0";
    var CaseActivities = GetDataUsingODataServiceWithJQuery(ODataSelect);
    if (CaseActivities != null) {
        if (CaseActivities.results.length > 0) {
            return false;
        }
        else {
            return true;
        }
    }
    else {
        return true;
    }
 
 
}

function GetContext() {
    var _context = null;
    if (typeof GetGlobalContext != "undefined")
        _context = GetGlobalContext();
    else if (typeof Xrm != "undefined")
        _context = Xrm.Page.context;
    return _context
}
 
 
DisplayError = function (cntrl, func, err) {
    alert("Control : " + cntrl + "\nODataCommonFunctions.: " + func + "\nError : " + err);
}
 
// ========== OData Serivce - JQuery Request Functions Start ==========
 
function GetDataUsingODataServiceWithJQuery(ODataSelect) {
    var resultOfGet = null;
    var CRMContext = GetContext();
    if (CRMContext != null) {
        var serverUrl = CRMContext.getServerUrl();
        var ODataEndpoint = "/XRMServices/2011/OrganizationData.svc";
        var ODataURL = serverUrl + ODataEndpoint + "/" + ODataSelect;
        try {
            $.ajax({
                type: "GET",
                contentType: "application/json; charset=utf-8",
                datatype: "json",
                async: false,
                url: ODataURL,
                beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Accept""application/json"); },
                success: function (data, textStatus, XmlHttpRequest) {
                    resultOfGet = data.d;
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    DisplayError("ODataService""Fetch", textStatus + " - " + JSON.parse(XMLHttpRequest.responseText).error.message.value);
                    //resultOfGet = null;
                }
            });
        } catch (e) {
            DisplayError("ODataService""Fetch", e.description);
            //resultOfGet = null;
        }
    }
    return resultOfGet;
}
function updateRecord(id, entityObject, odataSetName) {     var jsonEntity = window.JSON.stringify(entityObject);     // Get Server URL     var serverUrl = Xrm.Page.context.getServerUrl();     //The OData end-point     var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";     //Asynchronous AJAX function to Update a CRM record using OData     $.ajax({         type: "POST",         contentType: "application/json; charset=utf-8",         datatype: "json",         data: jsonEntity,         url: serverUrl + ODATA_ENDPOINT + "/" + odataSetName + "(guid'" + id + "')",         beforeSend: function (XMLHttpRequest) {             //Specifying this header ensures that the results will be returned as JSON.             XMLHttpRequest.setRequestHeader("Accept""application/json");             //Specify the HTTP method MERGE to update just the changes you are submitting.             XMLHttpRequest.setRequestHeader("X-HTTP-Method""MERGE");         },         success: function (data, textStatus, XmlHttpRequest) {             alert("Case resolved successfully");         },         error: function (XmlHttpRequest, textStatus, errorThrown) {             if (XmlHttpRequest && XmlHttpRequest.responseText) {                 alert("Error while updating " + odataSetName + " ; Error – " + XmlHttpRequest.responseText);             }         }     }); }



4.Writing the plugin:
Create a plugin as given below


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Xrm.Sdk;
using System.ServiceModel;
using System.Diagnostics;
using System.Data.Services;
using System.Data.Services.Client;
using contoso;
using System.Xml;
using Microsoft.Crm.Sdk.Messages;
 
 
namespace Xrm.Case
{
   public class IncidentPostUpdate:IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            contoso.Incident IncRec;
 
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
 
 
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"is Entity)
            {
 
                //Verify that the entity represents an Case
                if (((Entity)context.InputParameters["Target"]).LogicalName != contoso.Incident.EntityLogicalName || context.MessageName != "Update")
                    return;
                else
                    IncRec = ((Entity)context.InputParameters["Target"]).ToEntity<contoso.Incident>();
            }
            else
            {
                return;
            }
 
            try
            {
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
 
 
                using (var serenaContext = new SerenaContext(service))
                {
 
                    
                        if (context.Depth == 1)
                        {
 
                            if (IncRec.new_IsCaseResolved == true)
                            {
 
                                contoso.Incident inc = new Incident();
 
                                inc.new_IsCaseResolved = false;
                                inc.Id = IncRec.Id;
                                service.Update(inc);
 
                      
                                 List<contoso.ActivityPointer> caseOpenActivities = serenaContext.ActivityPointerSet
                                .Where(a => a.StateCode == ActivityPointerState.Open && a.RegardingObjectId.Id ==IncRec.Id)
                                .Select(a => new contoso.ActivityPointer
                                {
                                    Id = a.Id
                                }).ToList<contoso.ActivityPointer>();
 
                                 if (caseOpenActivities != null && caseOpenActivities.Count > 0)
                                 {
                                     throw new InvalidPluginExecutionException("Close all the Open activities associated with Case before closing the Case");
                                 }
                                 else
                                 { 
                                    // Create the incident's resolution.
                                    Entity caseResolution = new Entity("incidentresolution");
                                    caseResolution.Attributes.Add("incidentid"new EntityReference("incident", IncRec.Id));
                                    caseResolution.Attributes.Add("subject""Closed");
 
 
                                    // Close the incident with the resolution.         
 
                                    CloseIncidentRequest req = new CloseIncidentRequest();
                                    req.IncidentResolution = caseResolution;
                                    req.RequestName = "CloseIncident";
                                    OptionSetValue o = new OptionSetValue();
                                    o.Value = 5;
                                    req.Status = o;
 
                                    CloseIncidentResponse resp = (CloseIncidentResponse)service.Execute(req);
                                 }
 
                             }
                        }
                                    
                    
                }
 
 
            }
            catch (InvalidPluginExecutionException)
            {
                throw;
            }
            catch (FaultException<OrganizationServiceFault> ex)
            {
                throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
            }
 
        }
    }
}


5.Register the plugin as per the below screen shots:




We are done with the customization to override the Resove case Please note some points.

1.In plugin I am using early bound approach you can go with late bound as you wish.
2.Please include "Json" and "jquery" file on Case form as they will we used by the "updateRecord" method.


Hope it helps you.


Regards,
Yusuf