Bhoopathi

"Be Somebody Nobody Thought You could Be"

Thursday, March 9

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 <RibbonDiffXml> with 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();



Monday, March 6

Debugging Custom Workflow Activities with Plugin Registration Tool - MS CRM 2011

Debugging Custom Workflow Activities with Plugin Registration Tool - MS CRM 2011


I have been using the Plugin Registration Tool to debug Plugins for sometime now and it has turned out to be a real time saver as it let’s you run and debug your code without having to trigger application events. This shortens debug cycles and allows Plugins debugging by multiple developers simultaneously without halting the W3WP process.
I have just found out the Plugin Registration Tool can also help debug Custom Workflow Activities as well. Since this feature is currently not documented in the SDK or any other official literature, this post will guide you through.
Please note, currently this feature is not functioning well in Online deployments, hope MS will fix this soon.
In order to debug a Custom Workflow Activity, follow these steps:
  1. Activate the Plugin Registration Tool as an administrator. Make sure you are using the latest Plugin Registration Tool version from the latest SDK package.
  2. Register your Custom Workflow Activity using the Plugin Registration Tool.
  3. Create a Workflow Rule which reference your Custom Workflow Activity.
  4. If you don’t have the Profiler installed, click the ‘Install Profiler’ button in the inner menu. After it finishes installing, the Plugin Registration Tool shows the ‘Uninstall Profiler Button’ and a new item ‘Plug-in Profiler’ is added to the registered components
    image
  5. Click the ‘Plug-in Profiler’ item. Note the ‘Profile Workflow’ button appearing in the inner top menu
    image
  6. Click the ‘Profile Workflow’ button to open the Profile Setting window. From the Workflow picklist, select the Workflow Rule which contains the Custom Workflow Activity requires debugging
    image
  7. Check the Custom Workflow Activity requires debugging. Select ‘Persist to Entity’ radio option and click ‘OK’. Copy the value In the Persistence Key field to your clipboard
    image
  8. Notice the Profiled item added under the Plug-in Profiler root
    image
  9. Go to your CRM organization and trigger the relevant Workflow. In my example, this is a manual Workflow rule.
    image
  10. Go to Settings –> Extensions –> Plug-in Profiles. If you can’t locate it, refresh the window.
    image
  11. Open the relevant Plug-in Profile record, make sure the Persistence Key matches the one you have copied earlier
    image
  12. Click the Serialized Profile tab and copy the value in the Serialized Profile filed
    image
  13. Create a new text file and copy the Serialized Profile string into it. Save the file
  14. Go Back to the Plugin Registration Tool, select the profile created earlier and click the Debug button in the inner toolbar
    image
  15. In the opened Debug window, select the newly created text file in the the Profile Location field and the Custom Workflow Activity assembly in the Workflow Activity field
    image
  16. Go to Visual Studio, where the Custom Workflow Activity project is opened. Compile your code and locate the Custom Workflow Activity assembly and PDB file in the “…\Program Files\Microsoft Dynamics CRM\Server\bin\assembly” folder
  17. Attach the debugger to the Plugin Registration Tool Process. Put some break point in your code and click the Start Execution button in the Plugin Registration Tool Debug Window.
You are done. The Breakpoint should be hit and from now on you can edit your code and debug locally against the Plugin Registration Tool.
Now go get productive.

Debugging Custom Workflow Activities - MS CRM 2016



Debugging custom workflow Activities - MS CRM 2016


Plugin Registration tool can be used to debug not just plugin assemblies, but also custom workflow assemblies. I am not sure how well known this feature is, as I could not find any documentation about this in msdn.
Prerequisite
Use the correct version of Plugin Registration tool for your organisation. I could not use Plugin Registration tool that came along with CRM SDK 7.1.1, to debug a workflow assembly running in CRM 2015 Update 0.1 (7.0.1). I could however use Plugin Registration tool 8.0.0.7198 to debug workflow assembly running in CRMOnline 2016 (8.0.1.79). So, it seems the major version and minor version have to match to enable workflow assembly debugging.
After installing the profile, select the plugin profile node. You will now see a new button called “Profile Workflow”
Workflow Profile Button
Next, choose the CRM workflow which contains the custom workflow assembly. If the workflow has multiple custom workflow assembly steps, you will see each of these in this screen. You can choose the assembly to profile. It is best to choose “Persist to Entity” option, as you won’t see the exception when it is thrown by the workflow.Profile Settings

Once you click OK, a clone of the workflow will be created. It will have “(Profiled)” in the end. Your original workflow will now be in “Draft” state.
Workflow Cloned
Now execute the profiled workflow manually. Confirm that the workflow has finished running.
Workflow Log
Once the workflow has completed running, you can now use the serialised profile to debug the workflow assembly. After you click the “Replay Plugin Execution” button you will see this screen, which will help you to select the correct profile record.
Debug Profile Selection
I ran the workflow manually only once and hence there is only one profile row. If the workflow ran multiple times, you will see multiple rows. After you click select, you’ll then have to choose the correct workflow assembly that matches this profile.
Start Debug
Now attach the Visual Studio Debugger to the Plugin Registration Tool. Now is also a good time to put couple of breakpoints in the workflow assembly code in Visual Studio. Once you click “Start Execution”, the control should now be transferred to Visual Studio to facilitate debugging.
Visual Studio Debug
The behaviour is exactly same as plugin debugging. You can step though the code, understand the root cause of any weird behaviour and resolve it. Once you complete the execution, you will see the trace logs in the profiler.
Debug Result
One more thing: You can use this exact same process to debug an Action which has a custom assembly. Here is how the profile looks when an action with custom workflow assembly is profiled.
Debug an action
Things to note:
  1. When a workflow step is profiled, the workflow assembly containing this activity is cloned and registered as a profiled workflow assembly. It is this assembly that is used in the workflow that has the name ending with “(Profiled)”
  2. Even though you can see the workflow being profiled, stopping the workflow profile using the Plugin Registration tool seems impossible. You can see what is being profiled.Profiled Workflow
  3. In order to stop profiling, you’ll have to
    • Unpublish and delete the workflow/action that ends with “(Profiled)“
    • Delete the weirdly named assembly (all guid name) from the “Default Solution“. This will be under the “Plugin Assemblies” nodeCloned Workflow Assembly
I hope this technique will help you to debug custom workflow assemblies quite easily. Happy debugging.

Thursday, March 2

iframe onSave Events in MS CRm 2011

 //1.Save record embedded in iframe
//Account form with iframe, that displays contact form. Requirement is that when user press “save” button on account form, contact in iframe should be also saved.
var iframeXrmPage = Xrm.Page.getControl(“IFRAME_contact”).getObject().contentWindow.contentIFrame.Xrm.Page;
// 2. Suppose this is our custom entity named “new_mycustomentity” and we would like to show it in inside iframe within a custom aspx page.
//Users can create the new record from within the custom page.
//So we set the Iframe src to the url for creating new my custom entity record i.e.
//<iframe id=”IFRAME_NEWCUSTOMENTITY” frameborder=”0″ runat=”server”
//src = “http://localhost/Contoso/main.aspx?etn=new_mycustomentity&pagetype=entityrecord&#8221; & gt;
//However this is how it appears within in IFrame with no ribbons in it.
//So the next step would be to hide the blank space on the top as well as left navigation bar.Now we can use the following JavaScript that will hide the left navigation pane and blank ribbon.http://bingsoft.wordpress.com/2010/09/09/mscrm-2011-hide-areas-of-a-form/
function HideArea() {
// Hide the Ribbon Toolbar and move the form Content area to the top of the window
window.parent.document.getElementById(“crmTopBar”).style.display = “none”;
window.parent.document.getElementById(“crmContentPanel”).style.top = “0px”;
// Move Form Content area up to top of window, initial style.top is 135px
// set it to the height of the iframe
window.parent.document.getElementById(‘contentIFrame’).style.height = “400px”;
// Hide Left Hand Nav bar / pane
document.getElementById(“crmNavBar”).parentElement.style.display = “none”;
document.getElementById(“tdAreas”).parentElement.parentElement.parentElement.parentElement.colSpan = 2;
// Hide the Form Footer Bar
document.getElementById(“crmFormFooter”).parentElement.style.display = “none”;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// 3. How do I Validate with OnChange?
//Luckily this isn’t really that big of a deal. There are several options and its really whatever is best for you.
//Option 1: Blank the field.
//By far the easiest option is to just clear the field after prompting the user. The only downside is the user has to re-enter all of the data again.
function example(obj){
var rgCell = /[0-9]{3}-[0-9]{3}-[0-9]{4}/;
var sVal = obj.getEventSource().getValue();
if (rgCell.test(sVal)) {
// valid
} else {
// Invalid phone number
alert(‘Please enter a valid phone number (ex. 123-123-1234).’);
obj.getEventSource().setValue(”);
}
}
//Option 2: Utilize the OnSave
//There is a little more effort involved here, but a better experience for the user.
function example(obj){
var rgCell = /[0-9]{3}-[0-9]{3}-[0-9]{4}/;
var sVal = Xrm.Page.getAttribute(“mobilephone”).getValue(); //obj.getEventSource().getValue();
if (rgCell.test(sVal)) {
// valid
} else {
// Invalid phone number
alert(‘Please enter a valid phone number (ex. 123-123-1234).’);
Xrm.Page.getAttribute(“mobilephone”).controls.get(0).setFocus(); // only fires onSave
if (obj.getEventArgs() != null)
obj.getEventArgs().preventDefault();
}
}

Hide Insert Template Button in Email – IFrame Form

// Hide Insert Template Button in Email – IFrame Form
Some times we may get the requirement to hide the Insert Template button on the Inner Email iframe as shown velow. To hide this button call the below function in Form onLoad EventEmailTemp
function HideInsertTemplateButton()
{
var getInnerEmailFrame = window.top.document.getElementById(‘contentIFrame’);
var emailFrameDoc = getInnerEmailFrame.contentDocument ||      getInnerEmailFrame.contentWindow.document;
var el = emailFrameDoc.getElementById(‘idinserttemplate’);
if (el){
el.parentNode.removeChild(el);
}
}

Pass Custom Parameters to The HTML Web Resource through Iframe -XRM2011

Pass Custom Parameters to The HTML Web Resource through Iframe -XRM2011
Pass XRM Form Data to the web resource as Custom Parameters as follows:
function SendCustomUrlToIframe(ifarmeUrl, iFrame) {

 var customerId = Xrm.Page.data.entity.getId();

 if (customerId != null) 
{
  Xrm.Page.getControl(iFrame).setSrc(ifarmeUrl + "&id=" + customerId); 
}
}

Another Example:

The following sample shows you how to set the src property for the IFRAME and any parameters by using the onChange event of an option set field.
JScript
//Get the value of an option set attribute
var value = Xrm.Page.data.entity.attributes.get("new_pagechooser").getValuewTarget = "";
//Set the target based on the value of the option set
switch (value) {
    case 100000001:
        newTarget = "http://myServer/test/pageOne.aspx";
        break;
    default:
        newTarget = "http://myServer/test/pageTwo.aspx";
        break;
}
//Get the default URL for the IFRAME, which includes the 
// query string parameters
var IFrame = Xrm.Page.ui.controls.get("IFRAME_testar Url = IFrame.getSrc();
// Capture the parameters
var params = Url.substr(Url.indexOf("?"));
//Append the parameters to the new page URL
newTarget = newTarget + params;
// Use the setSrc method so that the IFRAME uses the
// new page with the existing parameters
IFrame.setSrc(newTarget);
Cheers,
Leave a comment

Accessing Xrm.Page through JavaScript MS CRM form in an IFrame

Accessing Xrm.Page or CrmForm through JavaScript from an html page showing CRM form in an IFrame and Saving data inside Iframe

Suppose we have an html page having an iframe that shows a MS CRM Record. If we want to access the attributes on the form or call the save function from our html page(Iframe), we can do it in the following manner.
If you try from CRM 4.0 then use the below code
var crmForm =document.getElementById(“myIframe”).contentWindow.document.getElementById(“contentIFrame”)
.document.frames[0].document.forms[‘crmForm’];
If you try from CRM 5.0 then use the below code
var XrmPage =document.getElementById(“myIframe”).contentWindow.document.getElementById(“contentIFrame”)
.document.frames[0].Xrm.Page;
and if you want to save the Data filled in Html Page(Iframe) follow the below procedure to save the data.
  • First, let’s assume you have an iFrame inside an entity.
    Secondly, we need to uncheck the “Restrict cross-frame scripting” check box on the iFrame properties.
    Lastly, it’s a good idea to make sure our iFrame is using HTTPS to prevent mixed mode security warnings.

    Talking Directly

    If you try to talk directly to the iFrame via something like:
    Xrm.Page.ui.controls.get(‘IFRAME_opp’).getObject().contentWindow.document
    Unless you are On-Premise, you may encounter the “Access is Denied” warning. This will show itself when dealing with URLs on a different domain (or subdomain). Cross “domain” scripting is a security feature within the browser. Now an easy fix is to disable the browser settings, but this isn’t a good solution.

    Messaging

    Instead of talking directly, we need send a messages to our iFrame. To send a message, we’d do something like:
    Xrm.Page.ui.controls.get(‘IFRAME_opp’).getObject().contentWindow.postMessage(‘test’, “*”)
    To receive the message on the iFrame, you need to listen for the message event. Let’s take a look at the JavaScript on our example iFrame page:
    function receiveMessage(e)
    {
    if (e.origin == ‘https://way.crm.dynamics.com&#8217;)
    {
    if (e.data == ‘test’)
    {
    document.getElementById(‘msgBox’).innerHTML = ‘testing…<br />’ + e.origin + ‘<br />’ + e.data;
    }
    if (e.data == ‘save’)
    {
    saveForm();
    }
    }
    }
    saveForm = function()
    {
    document.getElementById(‘msgBox’).innerHTML = ‘saving…’;
    }
    window.attachEvent(“onmessage”, receiveMessage);
    For ref plese use click this link http://msdn.microsoft.com/en-us/library/cc197015(VS.85).aspx
    Cheers,

Microsoft Dynamics CRM 2013 Opportunity Error Fix: Object doesn’t support property or method ‘Form_onload’

Microsoft Dynamics CRM 2013 Opportunity Error Fix: Object doesn’t support property or method ‘Form_onload’

While recently working with a Microsoft Dynamics CRM 2013 online environment, an error appeared on the Opportunity form.
“There was an error with this field’s customized event.Field:windowEvent:onloadError:Object doesn’t support property or method ‘Form_onload’
This was a rather surprising error because there were only a few customizations on the Opportunity form and there was no custom code. After several failed attempts to remedy this by adding and removing fields, I started searching online. I was fortunate to find the thread, CRM 2013: Strange ‘Form_onload’ error message in opportunity, that provided a suggestion to update the XML due to missing references to system JavaScript. As easy as that may sound to some, implementation of the fix was not that straight forward. So here is how to fully fix the issue.
Within Dynamics CRM, navigate to Settings -> Solutions
  • Create a new solution and only add the opportunity entity.
  • Choose to not include the dependencies.
  • Export the solution as an unmanaged solution.
  • Download the solution’s zip file and extract it.
  • Open the Customizations.xml file.
  • Search within the customization file for the <clientincludes tag.
  • This is where the XML is missing. There may be several instances where the code will look like this:
<clientincludes />
  1. Replace the <clientincludes /> tag with the following XML:
<clientincludes>
        <internaljscriptfile src=”/_static/sfa/sfautil.js” />
        <internaljscriptfile src=”/_static/sfa/opps/opps.js” />
        <internaljscriptfile src=”/_static/sfa/quotes/qoi_script.js” />
        <internaljscriptfile src=”$webresource:Opportunity_main_system_library.js” />
</clientincludes>
  1. Once finished, save the XML file.
  2. Next, drag the modified customizations.xml file back into the solution’s zip file and select the “Copy and Replace” option.
  3. Finally, import the solution back into Dynamics CRM and publish all customizations.
If you need troubleshooting support for Microsoft Dynamics CRM, McGladrey offers a full range of services throughout the United States from implementation and optimization to development and support. Our professionals are certified for Microsoft Dynamics with the Gold Customer Relationship Management (CRM) Competency in the Microsoft Partner Network. Contact our professionals for more information on our services at 855.437.7202 or crm@mcgladrey.com.