Bhoopathi

"Be Somebody Nobody Thought You could Be"

Monday, March 6

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 opportunitythat 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.

Thursday, February 16

Improving Performance of CRM Forms with IFrames

Posted by Aiden Kaskela on Jan 16, 2015 3:02:43 PM

Microsoft Dynamics CRM has long supported Iframes on forms but the way they’re implemented usually has a negative impact on form load times. While I was researching the form load process in CRM, I came across a great topic on MSDN which describes how Iframes should be loaded for best performance. The article at ‘Write code for Microsoft Dynamics CRM forms’ (http://msdn.microsoft.com/en-us/library/gg328261.aspx) suggests using collapsed tabs to defer loading web resources, which means we can eliminate the load times for Iframes completely if you’re not going to use it. The idea is, instead of setting the Iframe URL in OnLoad you use the TabStateChange event, which fires when the Tab is expanded and collapsed.
To implement this we need to add a Javascript web resource for setting the URL, the form customizations with the tab and Iframe, and update the tab event to call the Javascript. In this scenario we’re going to set up an Iframe to show an Account’s website.

Setting up the Web Resource

Go to your default (or named) solution and add a new Web Resource of type Script (Jscript). The name of my script is cobalt_DeferredFormLoad. After saving the resource, click on the Text Editor button to enter your script.
frame1
This is the script I’m using to set the URL. It’s quasi-generic, and will work for any entity where there is a website field on the form. The function takes in the name of the tab, the frame, and the attribute of the website.
function LoadIFrame(tabName, iframeName, websiteAttribute) {
    if (tabName != null && iframeName != null && websiteAttribute!= null ) {
        var isTabExpanded = (Xrm.Page.ui.tabs.get(tabName).getDisplayState() == "expanded");
        var websiteUrl = Xrm.Page.getAttribute("websiteurl").getValue();
        if (isTabExpanded == true && websiteUrl) {
            var IFrame = Xrm.Page.ui.controls.get(iframeName);
            if (IFrame != null) {
                IFrame.setSrc(websiteUrl);
            }
        }
    }
}

Adding the Form Customizations

From the Account form, insert a new Tab and leave the default values. Click in the Section area of the new tab and insert a new Iframe from the Ribbon Bar. Give the frame an appropriate name (IFRAME_CompanyWebsite) and any default URL. I unchecked ‘Display label on the Form’ because the tab label looks good on its own.
frame2
Now that the Iframe is setup you need to configure the Tab properties to load the Iframe. Under the Display tab, give an appropriate name and label, and uncheck ‘Expand this tab by default’.
frame3

Configuring the Event

With the Tab properties open, go to the Events tab, Add your new web resource, then Add a new Event Handler
frame4
In the Event Handler screen, fill in the name of the Function from the Javascript (LoadIFrame), and in the parameters section, list the parameters that need to be passed in the to function. The parameters are the name of the Tab, the name of the Iframe, and the name of the field that contains the URL to set. Remember that you’re specifying a string value and each parameter should be enclosed with a single quote mark.
frame5
Once you save and publish the customizations you can verify the results on your entity. Open the account form and find your new Tab, expand it, and verify everything opens correctly.

Wednesday, February 15

Calling a Workflow from Ribbon Button - MS CRM

Friday, February 3

How to copy Microsoft CRM 2011 organization on the same server


There are many reasons to copy organizations, one of the most common - for testing purpose.
You can do as following:
1. Select a database in SQL Server Management Studio which will be copied (TEST_MSCRM). Right click on the target database -> Tasks -> Backup.



2. Select Full for Backup type and press OK.

3. Right Click on Databases -> Restore Database.

4. Put the name of new database (TEST2_MSCRM) and select file from local disc a copy of TEST_MSCRM.bak.

5. Open CRM Deployment Manager -> Import Organization Wizard.
6. Select SQL server and database (TEST2_MSCRM) and Next.

7. Enter a Display name TEST2 and press Next.

8. Enter Report Server URL and press Next.

9. Select Automatically Map Users as recommended and press Next.

8. Press Import.
9. Press Finish.

10. Congratulations. New organization is created.
11. Go to Internet Explorer and enter address http://your_server _name/TEST2 and you will see a new fresh copy of your organization.