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

Thursday, April 4, 2013

Unable to attach to the crashing process. A debugger is already attached

Hi All, recently i was trying to debug java script in CRM 2011. I have added debugger; in the java script and enabled script debugging on IE. Getting the debugger prompt window, but after selecting VS2010 to debug, I was unable to debug java script using VisualStudio2010, getting the following error.


I tried using IE developer tool to debug, its working fine. After some analysis & troubleshooting, I came to know that my IE recently upgraded to IE10 by windows updates. I tried uninstalling IE10 updates, it asked for system reboot. After the reboot, IE degraded to IE9 and i was able to debug javascript using VisualStudio :)

 It looks like a bug in IE10. Hope Microsoft will resolve soon!!!

Hope it helps!!!

Wednesday, April 3, 2013

Unhandled Exception: System.ServiceModel.Security.MessageSecurityException: The security timestamp is invalid because its creation time ('2013-04-03T12:49:05.000Z') is in the future

While connecting to Plugin Registration Tool, i got the following error




Unhandled Exception: System.ServiceModel.Security.MessageSecurityException: The security timestamp is invalid because its creation time ('2013-04-03T12:49:05.000Z') is in the future. Current time is '2013-04-03T12:41:50.807Z' and allowed clock skew is '00:05:00'.

Server stack trace: 
   at System.ServiceModel.Security.SecurityTimestamp.ValidateFreshness(TimeSpan timeToLive, TimeSpan allowedClockSkew)
   at System.ServiceModel.Security.SecurityTimestamp.ValidateRangeAndFreshness(TimeSpan timeToLive, TimeSpan allowedClockSkew)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ReadTimestamp(XmlDictionaryReader reader)
   at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteFullPass(XmlDictionaryReader reader)
   at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
   at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessageCore(Message& message, TimeSpan timeout)
   at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout)
   at System.ServiceModel.Security.SecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
   at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
   at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Microsoft.IdentityModel.Protocols.WSTrust.IWSTrustContract.Issue(Message message)
   at Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannel.Issue(RequestSecurityToken rst, RequestSecurityTokenResponse& rstr)
   at Microsoft.Xrm.Sdk.Client.ServiceConfiguration`1.Issue(AuthenticationCredentials authenticationCredentials)
   at Microsoft.Xrm.Sdk.Client.ServiceConfiguration`1.AuthenticateInternal(AuthenticationCredentials authenticationCredentials)
   at Microsoft.Xrm.Sdk.Client.ServiceConfiguration`1.AuthenticateCrossRealm(ClientCredentials clientCredentials, String appliesTo, Uri crossRealmSts)
   at Microsoft.Xrm.Sdk.Client.ServiceProxy`1.AuthenticateCore()
   at Microsoft.Xrm.Sdk.Client.ServiceProxy`1.ValidateAuthentication()
   at Microsoft.Xrm.Sdk.Client.ServiceContextInitializer`1.Initialize(ServiceProxy`1 proxy)
   at Microsoft.Xrm.Sdk.Client.OrganizationServiceContextInitializer..ctor(OrganizationServiceProxy proxy)
   at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.RetrieveMultipleCore(QueryBase query)
   at Microsoft.Crm.Tools.PluginRegistration.OrganizationServiceExtensions.RetrieveMultipleAllPages(IOrganizationService service, QueryBase query)
   at Microsoft.Crm.Tools.PluginRegistration.OrganizationHelper.LoadMessages(CrmOrganization org, ProgressIndicator prog)
   at Microsoft.Crm.Tools.PluginRegistration.MainForm.LoadMessages(CrmOrganization org)
   at Microsoft.Crm.Tools.PluginRegistration.ConnectionsForm.OpenConnection(CrmOrganization org)

This happen because my system time is wrong. it running 10 mins slow. I just updated my system time with correct one, this issue got resolved and i'm able to login to Plugin Registration Tool.

Hope this helps!










Tuesday, March 26, 2013

0x8004D293 : Cannot update RequiredLevel of attribute CustomerId to SystemRequired

Hi All, recently I came across an issue while importing customization's from an existing environment to a new environment.

Error Details:
Entity Relationships || opportunity_customer_accounts || Failure || 0x8004D293 ||Cannot update              RequiredLevel of attribute CustomerId to SystemRequired.

 Source environment is upgraded to UP12, but the new UI not enabled on it. Target new environment by default came with UR12 new UI enabled.  Both the environments are CRM 2011 online.

During UR12, CustomerId field requirement level has been changed from System Required to Business Required. But CustomerId field on the opportunity is an OOB lookup field and we can't modify the requirement level.

 Its a known issue & documented  at http://msdn.microsoft.com/en-us/library/gg309589.aspx




Solution:

1. Enabling new UI in the Source environment. During new UI enable process, CustomerId field requirement level auto upgraded to Business required.

   Follow the following step to upgrade CRM to new UI.

    Settings => Administration => Product Updates


 Updated UX forms avaiable only for Leads, Contacts, Accounts, Opportunities and Cases. New UI does not support java script and it has other limitations.
However you have an option to Turn on / off  the new sales and service process forms
http://rc.crm.dynamics.com/rc/2011/en-us/online/5.1_OSDP/help/source_sf_turn_on_sales_forms.htm


Hope it helps!!!

Sunday, February 24, 2013

Change Record Status using javascript in CRM 2011

Sometimes we needs to change the CRM record status in java script. Following is the java script code to change the record status(deactivate,activate,qualify etc.). In this example i'm going to deactivate a custom entity record.

 
function changeRecordStatus(RECORD_ID,stateCode,statusCode) {

        // create the SetState request
        var request = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
        request += "<s:Body>";
        request += "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
        request += "<request i:type=\"b:SetStateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
        request += "<a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
        request += "<a:KeyValuePairOfstringanyType>";
        request += "<c:key>EntityMoniker</c:key>";
        request += "<c:value i:type=\"a:EntityReference\">";
        request += "<a:Id>" + RECORD_ID + "</a:Id>";
        request += "<a:LogicalName>cmic_systemusersalesterritoryassociation</a:LogicalName>";
        request += "<a:Name i:nil=\"true\" />";
        request += "</c:value>";
        request += "</a:KeyValuePairOfstringanyType>";
        request += "<a:KeyValuePairOfstringanyType>";
        request += "<c:key>State</c:key>";
        request += "<c:value i:type=\"a:OptionSetValue\">";
        request += "<a:Value>"+stateCode+"</a:Value>";
        request += "</c:value>";
        request += "</a:KeyValuePairOfstringanyType>";
        request += "<a:KeyValuePairOfstringanyType>";
        request += "<c:key>Status</c:key>";
        request += "<c:value i:type=\"a:OptionSetValue\">";
        request += "<a:Value>"+statusCode+"</a:Value>";
        request += "</c:value>";
        request += "</a:KeyValuePairOfstringanyType>";
        request += "</a:Parameters>";
        request += "<a:RequestId i:nil=\"true\" />";
        request += "<a:RequestName>SetState</a:RequestName>";
        request += "</request>";
        request += "</Execute>";
        request += "</s:Body>";
        request += "</s:Envelope>";

        //send set state request
        $.ajax({
            type: "POST",
            contentType: "text/xml; charset=utf-8",
            datatype: "xml",
            url: Xrm.Page.context.getServerUrl() + "/XRMServices/2011/Organization.svc/web",
            data: request,
            beforeSend: function (XMLHttpRequest) {
                XMLHttpRequest.setRequestHeader("Accept", "application/xml, text/xml, */*");
                XMLHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
            },
            success: function (data, textStatus, XmlHttpRequest) {
                Xrm.Page.ui.close();
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert(errorThrown);
            }
        });
   

}

//Deactivating custom entity record
changeRecordStatus(Xrm.Page.data.entity.getId(),1,2);


Hope it helps!!!