Showing posts with label Microsoft Dynamics crm 2011. Show all posts
Showing posts with label Microsoft Dynamics crm 2011. Show all posts

Friday, June 15, 2012

Microsoft Dynamics CRM 2011 Create new case from account's homepage ribbon


Microsoft Dynamics CRM 2011 Create new case from account's homepage ribbon Or cut the clicks

This is a how to create new case from account grid using ribbon button, just like if you would create the case from case sub grid in account form. It gets all the attributes mapping from related account.
The idea behind it was to cut the time for creating new case, Instead of going to account homepage, opening the account form, click on case sub grid and then create the case, It will be just go to account homepage choose the account and create new case.
This is a real time saver.


1) Create new solution.
2) Add new web resource type JavaScript

var CASE_URL = "/main.aspx?etc=112&extraqs=%3f_CreateFromId%3d%257b{ACCOUNTID}%257d%26_CreateFromType%3d1&pagetype=entityrecord";
CreateNewCaseFromAccount = function(id)
{
                        //get accountid
                        var nakedId = id.replace("{", "").replace("}", "");
                        var caseUrl = CASE_URL.replace("{ACCOUNTID}", nakedId);
                        var caseUrl = Xrm.Page.context.prependOrgName(caseUrl);
                        window.open(caseUrl);
}
3) Add button to account's homepage ribbon to call CreateNewCaseFromAccount function. Two ways for adding the button to account.
1) Use Ribbon workbench.
2) The old fashion way, do it yourself.
a. Add account to solution.
b. Export solution.
c. Extract the solution file.
d. Open customizations.xml using your favorite notepad
e.Add the button to the RibbonDiffXml:

  <RibbonDiffXml>
        <CustomActions>
          <CustomAction Id="HomepageGrid.account.MainTab.Actions.CreateNewCase.CustomAction" Location="Mscrm.HomepageGrid.account.MainTab.Actions.Controls._children" Sequence="41">
            <CommandUIDefinition>
              <Button Id="HomepageGrid.account.MainTab.Actions.CreateNewCase" Command="HomepageGrid.account.MainTab.Actions.CreateNewCase.Command" Sequence="20" ToolTipTitle="Create New Case" LabelText="Create New Case" ToolTipDescription="Create New Case" TemplateAlias="o1" />
            </CommandUIDefinition>
          </CustomAction>
        </CustomActions>
        <Templates>
          <RibbonTemplates Id="Mscrm.Templates"></RibbonTemplates>
        </Templates>
        <CommandDefinitions>
          <CommandDefinition Id="HomepageGrid.account.MainTab.Actions.CreateNewCase.Command">
            <EnableRules>
              <EnableRule Id="HomepageGrid.account.MainTab.Actions.CreateNewCase.Command.EnableRule.SelectionCountRule" />
            </EnableRules>
            <DisplayRules />
            <Actions>
              <JavaScriptFunction FunctionName="CreateNewCaseFromAccount" Library="$Webresource:new_/CreateNewCase/CreateNewCase.js">
                <CrmParameter Value="FirstSelectedItemId" />
              </JavaScriptFunction>
            </Actions>
          </CommandDefinition>
        </CommandDefinitions>
        <RuleDefinitions>
          <TabDisplayRules />
          <DisplayRules />
          <EnableRules>
            <EnableRule Id="HomepageGrid.account.MainTab.Actions.CreateNewCase.Command.EnableRule.SelectionCountRule">
              <SelectionCountRule AppliesTo="SelectedEntity" Maximum="1" Minimum="1" Default="true" />
            </EnableRule>
          </EnableRules>
        </RuleDefinitions>
        <LocLabels />
      </RibbonDiffXml>

f. Import the solution back and publish.


Good luck.

This post was written before Dynamics CRM 2011 RU 8 and the new Xrm.utility, It changes only the way of opening new form the basic idea of this post stays the same.
For more information about Xrm.utility go to
http://jonasrapp.cinteros.se/2012/08/xrmutility-methods-in-ms-dynamics-crm.html
or many other posts that explains the new functions available.
 

Thursday, June 14, 2012

Dynamics CRM 2011 readonly form javascript


Dynamics CRM 2011 read-only form JavaScript.

With it does:
1)     Hides the content of a form with transparent div.
Pros:
1)     Easier way to disable all the controls of the form and enabling them while keeping all the logic of the form (pre disabled controls will keep be disabled).
2)     It's faster than going over all the controls and disabling them.
Cons:
1)     Partially Unsupported

How to guide:
1)     Create new JavaScript web resource
2)     Add this code:
            //Disable all form controls
            DisableForm = function() {
                        var iframeDoc = document;
                        var iframeBody = document.getElementById("crmFormTabContainer");
                        hideContent(iframeDoc, iframeBody);
                        Xrm.Page.ui.tabs.forEach(
                                    function(tab, index)
                                    {
                                                Xrm.Page.ui.tabs.get(index).add_tabStateChange(function()
                                                {
                                                            var iframeDoc = document;
                                                            var iframeBody = document.getElementById("crmFormTabContainer");
                                                            var roSpan = document.getElementById("readonlySpan");
                                                            if (roSpan != null) {
                                                                        iframeBody.removeChild(roSpan);
                                                            }
                                                            hideContent(iframeDoc, iframeBody);
                                                });
                                    }
                        );
            }

            hideContent = function(htmlDocument, htmlElement) {
                        var roSpan = htmlDocument.createElement("div");
                        roSpan.id = "readonlySpan";
                       
                        var roStyle = "position:absolute;";
                        roStyle += "z-index:1;";
                        roStyle += "left:0px;";
                        roStyle += "top:0px;";
                        roStyle += "height:"+htmlElement.scrollHeight+"px;";
                        roStyle += "text-align:center;";
                        roStyle += "font:72px Tahoma;";
                        roStyle += "opacity:0.20;";
                        roStyle += "-moz-opacity:0.20;";
                        roStyle += '-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";';
                        roStyle += 'filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)"';
                        roStyle += "filter: alpha(opacity=20);";
                        roStyle += "background-color:white;";

                        roSpan.style.cssText = roStyle;
                        htmlElement.appendChild(roSpan);
                        roSpan.innerHTML = "<div style='margin-top:30%;height:100px;'>READ ONLY</div>";
                        roSpan.style.zoom = 1;
            }
           
            //Enable all form control keep readonly / disable logic.
            EnableForm = function() {
                        var iframeBody = document.getElementById("crmFormTabContainer");
                        var roSpan = document.getElementById("readonlySpan");
                        if (roSpan != null) {
                                    iframeBody.removeChild(roSpan);
                        }
            }
3)     Add DisableForm function to onload event of the form.

**Another way to disable all the controls

Good luck.


Wednesday, March 21, 2012

Upgrade ISV folde code from mscrm 4.0 to mscrm 2011

This is the MSDN article "Upgrade Code in the ISV folder to Microsoft Dynamics CRM 2011"
It gives almost everything one needs for making sure his code runs on mscrm 2011.
But the one thing it doesn't mention, gave me hell today.
In multi organization deployment you need to include the organization name in the path to the isv folder.
for example:
in mscrm 4.0 the path was:
http://crm2011/isv/...
In 2011 the path needed is
http://crm2011/organization name/isv...
otherwise it tries to authenticate the user with the user's default organization which might be different then the one needed.

Thanks for
http://nishantrana.wordpress.com/2011/03/17/showing-a-custom-aspx-deployed-in-isv-in-iframe-of-crm-form-crm-2011/. Without it I would have kept struggling with the code upgrade for quite some time.

One last thing:
It is better to really upgrade the code in ISV folder into something that stands by its own like WebResource(HTML, Silverlight) or separate asp.net application with it's own application pool. The ISV folder is officially deprecated.

Monday, November 28, 2011

Dynamics crm 2011 n to n lookup

N:N lookup in Dynamics CRM 2011.

For to 4.0 version: http://dynamicslollipops.blogspot.com/2011/07/mscrm-40-nn-lookup-field.html

Prerequest customization:
1) 1:N relation, and lookup placed on the form.
2) N:N relationship for holding the values.

Walkthrough:
1) Create new javascript webresource with the following code:

var CRM_FORM_TYPE_CREATE = 1;

RetreiveAssociatedEntities = function(relationshipSchemaName, entity1SchemaName, entity1KeyValue, retreiveAttribute) {
    var fetchXml = "<fetch mapping='logical'>"
    + "  <entity name='" + relationshipSchemaName + "'>"
    + "    <all-attributes />"
    + "    <filter>"
    + "      <condition attribute='" + entity1SchemaName + "id' operator='eq' value ='" + entity1KeyValue + "' />"
    + "    </filter>"
    + "  </entity>"
    + "</fetch>";

    var fetchResults = Fetch(fetchXml);

    var nodeList = fetchResults.selectNodes("resultset/result");

    var returnList = new Array();
    if (nodeList == null || nodeList.length == 0) {
        return returnList;
    } else {
        for (i = 0; i < nodeList.length; i++) {
            var idValue = nodeList[i].selectSingleNode('./' + retreiveAttribute).nodeTypedValue;
            returnList[i] = idValue;
        }
        return returnList;
    }
}
MischiefMayhemSOAP = function(serviceUrl, xmlSoapBody, soapActionHeader, suppressError) {
    var xmlReq = "<?xml version='1.0' encoding='utf-8'?>"
    + "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'"
    + "  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'"
    + "  xmlns:xsd='http://www.w3.org/2001/XMLSchema'>"
    + GenerateAuthenticationHeader()
    + "  <soap:Body>"
    + xmlSoapBody
    + "  </soap:Body>"
    + "</soap:Envelope>";

    var httpObj = new ActiveXObject("Msxml2.XMLHTTP");

    httpObj.open("POST", serviceUrl, false);

    httpObj.setRequestHeader("SOAPAction", soapActionHeader);
    httpObj.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    httpObj.setRequestHeader("Content-Length", xmlReq.length);

    httpObj.send(xmlReq);

    var resultXml = httpObj.responseXML;

    var errorCount = resultXml.selectNodes("//error").length;
    if (errorCount != 0) {
        var msg = resultXml.selectSingleNode("//description").nodeTypedValue;

        if (typeof (suppressError) == "undefined" || suppressError == null) {
            alert("The following error was encountered: " + msg);
        }

        return null;
    } else {
        return resultXml;
    }
}

Fetch = function(fetchXml) {
    var xmlSoapBody = "<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"
    + "  <fetchXml>"
    + FetchEncode(fetchXml)
    + "  </fetchXml>"
    + "</Fetch>";

    var fetchResponse = MischiefMayhemSOAP("/MSCRMServices/2007/CrmService.asmx", xmlSoapBody, "http://schemas.microsoft.com/crm/2007/WebServices/Fetch");

    if (fetchResponse != null) {
        var fetchResults = new ActiveXObject("Msxml2.DOMDocument");

        fetchResults.async = false;
        fetchResults.resolveExternals = false;
        fetchResults.loadXML(fetchResponse.text);

        return fetchResults;
    } else {
        return null;
    }
}
FetchEncode = function(strInput) //_HtmlEncode
{
    var c;
    var HtmlEncode = '';

    if (strInput == null) {
        return null;
    }
    if (strInput == '') {
        return '';
    }

    for (var cnt = 0; cnt < strInput.length; cnt++) {
        c = strInput.charCodeAt(cnt);

        if (((c > 96) && (c < 123)) ||
  ((c > 64) && (c < 91)) ||
  (c == 32) ||
  ((c > 47) && (c < 58)) ||
  (c == 46) ||
  (c == 44) ||
  (c == 45) ||
  (c == 95)) {
            HtmlEncode = HtmlEncode + String.fromCharCode(c);
        }
        else {
            HtmlEncode = HtmlEncode + '&#' + c + ';';
        }
    }

    return HtmlEncode;
}

AssociateEntities = function(moniker1name, moniker1id, moniker2name, moniker2id, RelationshipName) {
    var authenticationHeader = GenerateAuthenticationHeader();
    // Prepare the SOAP message.
    var xml = "<?xml version='1.0' encoding='utf-8'?>";
    xml += "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance\' xmlns:xsd='http://www.w3.org/2001/XMLSchema\'>";
    xml += authenticationHeader;
    xml += "<soap:Body><Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'><Request xsi:type='AssociateEntitiesRequest'>";
    xml += "<Moniker1><Id xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>" + moniker1id + "</Id>";
    xml += "<Name xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>" + moniker1name + "</Name></Moniker1>";
    xml += "<Moniker2><Id xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>" + moniker2id + "</Id>";
    xml += "<Name xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>" + moniker2name + "</Name></Moniker2>";
    xml += "<RelationshipName>" + RelationshipName + "</RelationshipName>";
    xml += "</Request></Execute></soap:Body></soap:Envelope>";

    // Prepare the xmlHttpObject and send the request.
    var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
    xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
    xHReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
    xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    xHReq.setRequestHeader("Content-Length", xml.length);
    xHReq.send(xml);

    // Capture the result.
    var resultXml = xHReq.responseXML;

    // Check for errors.
    var errorCount = resultXml.selectNodes('//error').length;

    if (errorCount != 0) {
        var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
        alert(msg);
    }
}

DisassociateEntities = function(moniker1name, moniker1id, moniker2name, moniker2id, RelationshipName) {
    var authenticationHeader = GenerateAuthenticationHeader();
    // Prepare the SOAP message.
    var xml = "<?xml version='1.0' encoding='utf-8'?>";
    xml += "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance\' xmlns:xsd='http://www.w3.org/2001/XMLSchema\'>";
    xml += authenticationHeader;
    xml += "<soap:Body><Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'><Request xsi:type='DisassociateEntitiesRequest'>";
    xml += "<Moniker1><Id xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>" + moniker1id + "</Id>";
    xml += "<Name xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>" + moniker1name + "</Name></Moniker1>";
    xml += "<Moniker2><Id xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>" + moniker2id + "</Id>";
    xml += "<Name xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>" + moniker2name + "</Name></Moniker2>";
    xml += "<RelationshipName>" + RelationshipName + "</RelationshipName>";
    xml += "</Request></Execute></soap:Body></soap:Envelope>";

    // Prepare the xmlHttpObject and send the request.
    var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
    xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
    xHReq.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
    xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    xHReq.setRequestHeader("Content-Length", xml.length);
    xHReq.send(xml);

    // Capture the result.
    var resultXml = xHReq.responseXML;

    // Check for errors.
    var errorCount = resultXml.selectNodes('//error').length;

    if (errorCount != 0) {
        var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
        alert(msg);
    }
}

//returns the item location in array if not found -1
GetIndexFromArray = function(item, recordArr) {
    for (var i = 0; i < recordArr.length; i++) {
        if (recordArr[i] != null && recordArr[i].id == item) {
            return i;
        }
    }
    return -1;
}

/*"new_new_entity1_new_entity2new","new_multynewid", "new_entity2", "new_name"*/
FillMultiLookup = function(relationshipSchemaName, lookupSchemaName, relatedEntitySchemaName, relatedEntityPrimaryAttributeSchemaName) {
    var relatedValues = RetreiveAssociatedEntities(relationshipSchemaName, Xrm.Page.data.entity.getEntityName(), Xrm.Page.data.entity.getId(), relatedEntitySchemaName + "id");
    var value = new Array();
    for (var i = 0; i < relatedValues.length; i++) {
        value[i] = new Object();
        value[i].id = relatedValues[i];
        value[i].name = RetreiveAssociatedEntities(relatedEntitySchemaName, relatedEntitySchemaName, relatedValues[i], relatedEntityPrimaryAttributeSchemaName)[0];
        value[i].typename = relatedEntitySchemaName;
    }
 crmForm.all[lookupSchemaName].DataValue = value;
}

UpdateN2N = function(nnId, relatedEntitySchemaName, relatedEntitySchemaId, lookupSchemaName) {
    var oldValues = RetreiveAssociatedEntities(nnId, Xrm.Page.data.entity.getEntityName(), Xrm.Page.data.entity.getId(), relatedEntitySchemaId);
 var value = crmForm.all[lookupSchemaName].DataValue;
    //if there's records in lookup
    if (value != null) {
        //go over all the related records and remove them if not in the new list (lookup)
        var temp = value;
        for (var i = 0; i < oldValues.length; i++) {
            //if not in the new list disassociate them
            var index = GetIndexFromArray(oldValues[i], temp);
            if (index == -1) {
                DisassociateEntities(Xrm.Page.data.entity.getEntityName(), Xrm.Page.data.entity.getId(), relatedEntitySchemaName, oldValues[i], nnId);
            }
            else { // if in the list remove them from the list
                temp[index] = null;
            }
        } //ends for
        //go over all the remaining records and associate them
        for (var i = 0; i < temp.length; i++) {
            if (temp[i] != null) {
                AssociateEntities(Xrm.Page.data.entity.getEntityName(), Xrm.Page.data.entity.getId(), relatedEntitySchemaName, temp[i].id, nnId);
            }
        }
    }
    else if (oldValues != null) {
        for (var i = 0; i < oldValues.length; i++) {
            DisassociateEntities(Xrm.Page.data.entity.getEntityName(), Xrm.Page.data.entity.getId(), relatedEntitySchemaName, oldValues[i], nnId);
        }
    }
}

FilterN2NLookup = function(filterByLookup, filterLookup, entityName, nnName, nnFrom, linkedEntityName, linkedAttributeName) {
    var filter = '';
    var values = filterByLookup.DataValue;
    if (values != null) {
        //filter = '<filters><filter entity="' + entityName + '"><condition attribute="' + attributeName + '" operator="in">';
        //for (var i = 0; i < values.length; i++) {
        //    filter += '<value uiname="' + values[i].name + '">' + values[i].id + '</value>';
        // }
        //filter += '</condition></filter></filters>';

        filter = '<link-entity entity="' + entityName + '" name="' + nnName + '" from="' + nnFrom + '" to="' + nnFrom + '" visible="false" intersect="true"><link-entity name="' + linkedEntityName + '" from="' + linkedAttributeName + '" to="' + linkedAttributeName + '"><filter type="and"><condition attribute="' + linkedAttributeName + '" operator="in">';
        for (var i = 0; i < values.length; i++) {
            filter += '<value uiname="' + values[i].name + '">' + values[i].id + '</value>';
        }
        filter += '</condition></filter></link-entity></link-entity>';

    }
    filterLookup.AddParam('filters', filter);
}

/*"new_new_entity1_new_entity2new","new_multynewid", "new_entity2", "new_name"*/
function ConvertN2N(relationshipSchemaName, lookupSchemaName, relatedEntitySchemaName, relatedEntityPrimaryAttributeSchemaName)
{
 document.getElementById(lookupSchemaName).setAttribute("lookupstyle", "multi");
 document.getElementById(lookupSchemaName).setAttribute("_lookupstyle", "multi");

 document.getElementById(lookupSchemaName).onchange = function(){UpdateN2N(relationshipSchemaName, relatedEntitySchemaName, relatedEntitySchemaName + "id", lookupSchemaName)};

 Xrm.Page.getAttribute(lookupSchemaName).setSubmitMode("never");

 if (crmForm.FormType != CRM_FORM_TYPE_CREATE) {
  FillMultiLookup(relationshipSchemaName, lookupSchemaName, relatedEntitySchemaName, relatedEntityPrimaryAttributeSchemaName);
 }
 else {
  Xrm.Page.getControl(lookupSchemaName).setDisabled(true);
 }
}

2) Add it to the form
3) Add to the onload 
   3.1) Function: ConvertN2N
   3.2) Parameters: N:N Relationship name, lookup attribute name, Related Entity Schema Name, Related Entity Primary Attribute Schema Name
(Example: "new_incident_new_problem", "new_problemid", "new_problem", "new_name")



That's it, everything else is inside the code. 
Plug and Play.

Sunday, November 27, 2011

Microsoft Dynamics CRM 2011 Performs better on IE 9

Microsoft Dynamics CRM 2011 Performs better on IE 9.
After few tests we ran on Microsoft Dynamics CRM 2011 vanilla, we have found that IE 9 performance improves by 1-2~ sec per form.

Open Create Account form:
IE 8  - 3~ sec.
IE 9 - 1-1.5 ~ sec.

Open update Account form
IE 8 - 3~ sec.
IE 9 - 1-1.5 ~ sec.

* Average time for 3 tests.