Thursday, July 18, 2013

Microsoft Dynamics CRM 2011 Reporting book


Recently I got a chance to review Microsoft Dynamics CRM 2011 Reporting  book by Damian Sinay. This book is really good one for the people who wants to learn reports in MS CRM. This book is a practical guide to the developers. provided complete details on reporting developers perspective. It has so many practical examples with nice explanation. For the beginners must read book to gets started on reports in CRM.
scope of this book only limited to reporting on Microsoft Dynamics CRM as the title of the book says.

If you wants this book, go through this link

I was really happy to review this excellent book. Thanks for the great book.

Keep smiling :)

Displaying view in an IFrame CRM 2011

I was getting number of requests to update my earlier post Displaying view in Iframe which broke after UR12. Sorry for the delay, Now I got sometime to update this article to make it work after UR12.

Scenario:  Displaying Primary Contact's 'All Activities' view in an I-Frame which is on Account form.


1. Create an Iframe on the Account form and add to the form. Iframe properties

  2. Add the following code into a web resource and attach web resource on to the form.


/// <summary>
/// loadIFrame method will be main method which needs to be called to Load View into IFrame
/// Here in this example we will be dsiplaying primary contact's All Activities on the Account form
/// </summary>

function loadIFrame() {
    
    // Get Primary Contact of Account
    var primarycontact = Xrm.Page.getAttribute("primarycontactid").getValue();
    if (primarycontact != null && primarycontact[0].id != null) {
        primarycontactId = primarycontact[0].id;

        window.fetchActivtities = new FetchViewer("IFRAME_ShowView"); // IFRAME_ShowView = ID of Iframe
        fetchActivtities.FetchXml = getFetchXml(primarycontactId); // Pass primarycontact GUID as parameter
        fetchActivtities.LayoutXml = getLayoutXml();
        fetchActivtities.Entity = "activitypointer";   //Fetching entity schema name
        fetchActivtities.QueryId = "{00000000-0000-0000-00AA-000010001902}"; // view GUID, here its 'All Activities' view GUID
        fetchActivtities.RegisterOnTab(1); //IFRAME TAB INDEX where Iframe located
    }

}


/// <summary>
/// Gets FetchXML
/// </summary>
/// <param name="primarycontactId">Accounts Primary Contact ID</param>

function getFetchXml(primarycontactId) {

    //  FetchXML Query of view, you can get it from Adv. Find or Customizations.xml 

    return '<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">'+
              '<entity name="activitypointer">'+
                '<attribute name="activitytypecode" />'+
                '<attribute name="subject" />'+
                '<attribute name="statecode" />'+
                '<attribute name="prioritycode" />'+
                '<attribute name="modifiedon" />'+
                '<attribute name="activityid" />'+
                '<attribute name="instancetypecode" />'+
                '<order attribute="modifiedon" descending="false" />'+
                '<filter type="and">'+
                  '<condition attribute="regardingobjectid" operator="eq"  value="'+primarycontactId+'" />'+
                '</filter>' +
                '<link-entity name="systemuser" from="systemuserid" to="owninguser" visible="false" link-type="outer" alias="activitypointerowningusersystemusersystemuserid">'+
                  '<attribute name="internalemailaddress" />'+
                '</link-entity>'+
              '</entity>' +
            '</fetch>';



}


/// <summary>
/// Layout of Gridview
/// </summary>

function getLayoutXml() {

    // grid layout, you can get easily from Customization.xml file
    return  '<grid name="resultset" object="4200" jump="subject" select="1" preview="1" icon="1">'+
                '<row name="result" id="activityid" multiobjectidfield="activitytypecode">'+
                  '<cell name="subject" width="180" />'+
                  '<cell name="regardingobjectid" width="110" />'+
                  '<cell name="activitytypecode" width="100" />'+
                  '<cell name="statecode" width="100" />'+
                  '<cell name="ownerid" width="120" />'+
                  '<cell name="prioritycode" width="100" />'+
                  '<cell name="scheduledstart" width="140" />'+
                  '<cell name="scheduledend" width="140" />'+
                  '<cell name="activitypointerowningusersystemusersystemuserid.internalemailaddress" width="100" disableSorting="1" />'+
                  '<cell name="createdby" width="100" />'+
                  '<cell name="instancetypecode" width="100" ishidden="1" />'+
                '</row>' +
              '</grid>';

}

/// <summary>
/// Fetch IFrame content
/// </summary>
function FetchViewer(iframeId) {

   
    var Instance = this;
    var vDynamicForm;
    var m_iframeTab;
    var m_iframeDoc;

    Instance.Entity = "";
    Instance.Iframe = null;
    Instance.FetchXml = "";
    Instance.QueryId = "";
    Instance.LayoutXml = "";

    Instance.RegisterOnTab = function (tabIndex) {
        Instance.Iframe = document.getElementById(iframeId);

        if (!Instance.Iframe)
            return alert("Iframe " + iframeId + " is undefined");

        m_iframeDoc = getIframeDocument();
        var loadingGifHTML = "<table height='100%' width='100%' style='cursor:wait'>";
        loadingGifHTML += "<tr>";
        loadingGifHTML += "<td valign='middle' align='center'>";
        loadingGifHTML += "<img alt='' src='/_imgs/AdvFind/progress.gif'/>";
        loadingGifHTML += "<div/><b>Loading View...</b>";
        loadingGifHTML += "</td></tr></table>";
        m_iframeDoc.body.innerHTML = loadingGifHTML;

        Instance.Refresh();

    }
    
    function RefreshOnReadyStateChange() {

        if (Instance.Iframe.readyState != 'complete')
            return;

        Instance.Refresh();
    }

    /// <summary>
    /// Loads Iframe with the view   
    /// </summary>
    Instance.Refresh = function () {

        if (!Instance.Iframe)
            return alert("Iframe " + iframeId + " is undefined");

        m_iframeDoc = getIframeDocument();

        Instance.Iframe.detachEvent("onreadystatechange", RefreshOnReadyStateChange);

        var create = m_iframeDoc.createElement;
        var append1 = m_iframeDoc.appendChild;

        var vDynamicForm = document.createElement("form");
        vDynamicForm.setAttribute('method', "post");
        vDynamicForm.setAttribute('name', "vDynamicForm");
        
        var FetchXml = document.createElement("input");
        FetchXml.setAttribute('type', "hidden");
        FetchXml.setAttribute('name', "FetchXml");
        vDynamicForm.appendChild(FetchXml);

        
        var LayoutXml = document.createElement("input");
        LayoutXml.setAttribute('type', "hidden");
        LayoutXml.setAttribute('name', "LayoutXml");
        vDynamicForm.appendChild(LayoutXml);

       
        var EntityName = document.createElement("input");
        EntityName.setAttribute('type', "hidden");
        EntityName.setAttribute('name', "EntityName");
        vDynamicForm.appendChild(EntityName);


        
        var DefaultAdvFindViewId = document.createElement("input");
        DefaultAdvFindViewId.setAttribute('type', "hidden");
        DefaultAdvFindViewId.setAttribute('name', "DefaultAdvFindViewId");
        vDynamicForm.appendChild(DefaultAdvFindViewId);

        
        var ViewType = document.createElement("input");
        ViewType.setAttribute('type', "hidden");
        ViewType.setAttribute('name', "ViewType");
        vDynamicForm.appendChild(ViewType);

        m_iframeDoc.body.appendChild(vDynamicForm)
        

        vDynamicForm.action = prependOrgName("/AdvancedFind/fetchData.aspx");
        vDynamicForm.FetchXml.value = Instance.FetchXml;
        vDynamicForm.LayoutXml.value = Instance.LayoutXml;
        vDynamicForm.EntityName.value = Instance.Entity;
        vDynamicForm.DefaultAdvFindViewId.value = Instance.QueryId;
        vDynamicForm.ViewType.value = 1039;
        vDynamicForm.submit();


        Instance.Iframe.attachEvent("onreadystatechange", OnViewReady);
    }

    function OnViewReady() {
        if (Instance.Iframe.readyState != 'complete') return;

        Instance.Iframe.style.border = 0;
        Instance.Iframe.detachEvent("onreadystatechange", OnViewReady);
        m_iframeDoc = getIframeDocument();
        m_iframeDoc.body.scroll = "no";
        m_iframeDoc.body.style.padding = "0px";
    }

    /// <summary>
    /// Gets Iframe content
    /// </summary>

    function getIframeDocument() {
        return Instance.Iframe.contentWindow.document;
    }

}



 
3. Now call loadIFrame() method on the form OnLoad.

That's it, it will shows the view on the Iframe.
Hope it helps!!!

Note:  System/Custom view can be displayed using view GUID. You can customize FetchXML or Grid Layout accordingly based on your requirement. But Adv.Find view's may work in some cases.

Disclaimer: This article is completely unsupported customization. use at your own risk. it might break with feature roll-ups.

Monday, July 15, 2013

Passing parameters to Navigation Link in CRM 2011

In CRM 2011 we have the option to add custom Navigation link. we can add external URL or webresource to the Navigation pane. I wants to add webresource to the navigation pane.

Added webresource to the navigation pane.


Now I wants to pass record GUID as parameter to the webresource. To pass entity properties to the Navigation link, we have to edit entity XML. Export the solution from CRM and then extract the zipfile.
Now open the Customizations.XML file in edit mode. Find the custom navigation link details in the XML, in my case "Custom Link" navigation link.

Modify the navigation link XML in the following way

<NavBarItem Id="navLink{e60ed59a-1121-0e37-65de-3432ed3982e4}" Icon="" Url="$webresource:new_mypage.html" Area="Info" Sequence="9600" PassParams="1"  >

                    <Titles>
                      <Title LCID="1033" Text="Custom Link" />
                    </Titles>
                  </NavBarItem>
                </NavBar>

 
I have added PassParams property to the XML which passes parameters to webresource.

PassParams =     0   do not pass parameters [default]
                           1  pass parameters.


For more information  click
Hope this helps!!!

Tuesday, July 9, 2013

Table alias a_065a97880625e1118ea61cc1def13751 is not unique amongst all top-level table and join aliases

Recently we have modified few views in CRM 2011 online. After modifying the views, we were not able to access the view in CRM. Getting the following error message.

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: System.Xml.XmlException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #2C52B8F9Detail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ErrorCode>-2147220970</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>System.Xml.XmlException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #2C52B8F9</Message>
  <Timestamp>2013-07-09T05:42:07.7326294Z</Timestamp>
  <InnerFault>
    <ErrorCode>-2147217104</ErrorCode>
    <ErrorDetails xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
    <Message>Table alias a_065a97880625e1118ea61cc1def13751 is not unique amongst all top-level table and join aliases</Message>
    <Timestamp>2013-07-09T05:42:07.7326294Z</Timestamp>
    <InnerFault i:nil="true" />
    <TraceText i:nil="true" />
  </InnerFault>
  <TraceText i:nil="true" />
</OrganizationServiceFault>


Looks like a bug with recent roll up's. Found the following article  to fix this issue
http://blog.salesmetrix.com/2013/02/08/corruption-of-views-dynamics-crm-2011-online-dec-2012-service-release/

work around provided in the article worked for me. Hope it helps someone..