Saturday, February 16, 2008

MSCRM 4.0 Client: Hiding Buttons by Id

To hide a button in MSCRM 4.0 with the button id:

    var objElement = document.getElementById('_MBcrmFormSaveAndClose');
    objElement.innerHTML='<SPAN><SPAN><SPAN><SPAN></SPAN></SPAN></SPAN></SPAN>';


A function can be created to show/hide buttons by providing the Button Id:

// show: bool. Show = true, Hide = false
// id: string. Button Id
// tags: string. Object to stored the HTML tags
crmForm.ShowButton = function(show, id, tags)
{
    // Retrieve relevant button element based on Id
    var objElement = document.getElementById(id);
    var returnValue = null;

    // Show Button
    if (show) 
    {
        // Ensure the HTML tags for showing button is available 
        if (tags != null) 
        {
            // Restore HTML tags for showing button
            objElement.innerHTML = tags;
        }
    }
    // Hide Button
    else
    {
        // Store the HTML tags so that it can be restored when showing button
        returnValue = objElement.innerHTML;
        objElement.innerHTML='<SPAN><SPAN><SPAN><SPAN></SPAN></SPAN></SPAN></SPAN>';
    }

    return returnValue;
}


To call the function to hide a button:

    crmForm.SaveAndCloseButtonTags = crmForm.ShowButton(false, 
        "_MBcrmFormSaveAndClose", crmForm.SaveAndCloseButtonTags);


To show the button:

    crmForm.SaveAndCloseButtonTags = crmForm.ShowButton(true, 
        "_MBcrmFormSaveAndClose", crmForm.SaveAndCloseButtonTags);


To remove the button completely:

    var objElement = document.getElementById('_MBcrmFormSaveAndClose');
    objElement.outerHTML='<SPAN><SPAN><SPAN><SPAN></SPAN></SPAN></SPAN></SPAN>';

Friday, February 15, 2008

MSCRM 4.0 Client: Hiding Buttons by ‘title’ Attribute

To hide a button in MSCRM 4.0 by the button title attribute:

var list = document.getElementsByTagName("LI");
var i = 0;

while (i < list.length) 
{
    if (list[i].getAttribute('title') == 'Save and Close') 
    {
        list[i].innerHTML='<SPAN><SPAN><SPAN><SPAN></SPAN></SPAN></SPAN></SPAN>';
    }
    i = i + 1;
}

Basically the button HTML will be as below (the button outerHTML property):
<LI class=ms-crm-Menu id=_MBcrmFormSaveAndClose title="Save and 
Close" onclick=window.execScript(action) tabIndex=-1 action="crmForm.SaveAndClose();"><SPAN 
class=ms-crm-Menu-Label><A class=ms-crm-Menu-Label onclick="return false;" 
tabIndex=-1 href="javascript:onclick();" target=_self><IMG class=ms-crm-Menu-ButtonFirst 
tabIndex=-1 alt="Save and Close" src="/_imgs/ico/16_saveClose.gif"><SPAN 
class=ms-crm-MenuItem-TextRTL tabIndex=0>Save and Close</SPAN></A></SPAN>

So, in order to hide the button, the tags can be replaced by:

    list[i].innerHTML='<SPAN><SPAN><SPAN><SPAN></SPAN></SPAN></SPAN></SPAN>';

If the button required to be shown again later (e.g. based on certain condition to show/hide), the HTML can be stored into a variable before replacing the tags with the codes shown above, for example:

    crmForm.CUST_SaveAndCloseHTML = list[i].innerHTML;
    list[i].innerHTML='<SPAN><SPAN><SPAN><SPAN></SPAN></SPAN></SPAN></SPAN>';

So, in order to show the button:
list[i].innerHTML = crmForm.CUST_SaveAndCloseHTML;

A function can be created to show/hide buttons (the function has been attached to the crmForm, so that it can be invoked by events triggered by any form element):

// show: bool. Show = true, Hide = false
// title: string. Button Title
// tags: string. Object to stored the HTML tags
// return value: HTML removed HTML tags (for hiding the button)
crmForm.ShowButton = function(show, title, tags)
{
    var returnValue = null;
    var list = document.getElementsByTagName("LI");
    var i = 0;
    
    // Show Button
    if (show) 
    {
        // Ensure the HTML tags for showing button is available 
        if (tags != null) 
        {
            while (i < list.length) 
            {
                if (list[i].getAttribute('title') == title) 
                {
                    // Restore HTML tags for showing button
                    list[i].innerHTML = tags;
                }
                i = i + 1;
            }
        }
    }
    // Hide Button
    else
    {
        while (i < list.length) 
        {
            if (list[i].getAttribute('title') == title) 
            {
                // Return the HTML tags has been removed for hiding 
                // the button so that it can be used to restore when 
                // showing the button
                returnValue = list[i].innerHTML;
                // Hide button
                list[i].innerHTML='<SPAN><SPAN><SPAN><SPAN></SPAN></SPAN></SPAN></SPAN>';
            }
            i = i + 1;
        }
    }

    return returnValue;
}

To call the function to hide a button (the return value has been stored into a property attached to crmForm, so that it can used again to restored the button for showing):

    crmForm.SaveAndCloseButtonTags = crmForm.ShowButton(false, 
            'Save and Close', crmForm.SaveAndCloseButtonTags);

To show the button (again, the return value has been stored into a property attached to crmForm):

    crmForm.SaveAndCloseButtonTags = crmForm.ShowButton(true, 
            'Save and Close', crmForm.SaveAndCloseButtonTags);

If the button need to be removed completely (instead of hiding which can be made visible again later), the hiding action should replace the outerHTML instead of innerHTML with 4 empty <SPAN> tags:

    list[i].outerHTML='<SPAN><SPAN><SPAN><SPAN></SPAN></SPAN></SPAN></SPAN>';

Sunday, February 10, 2008

MSCRM 4.0 Workflow: Workflow forever at the Waiting state

If encountered workflows never get executed. First step is to create a simple workflow (for whatever entity, e.g. Update a value upon creation), and perform an action that can trigger this workflow.

Secondly check the System Jobs to find out whether there is any issue with the workflow. For example, the workflow probably at the Waiting state (Status Reason) for long period of time (or forever):


Use Advanced Find to reveal the Error Code and Message Columns:


If the Message column shows the error:
System.Net.WebException: The request failed with HTTP status 400: Bad Request.

This could be due to the Async Service was unable to connect to the correct URL. To verify, connect to the database: MSCRM_CONFIG, and execute statements below:

SELECT NVarCharColumn
FROM deploymentproperties
WHERE columnname = 'AsyncSdkRootdomain'

SELECT NVarCharColumn
FROM deploymentproperties
WHERE columnname = 'ADSdkRootdomain'

SELECT NVarCharColumn
FROM deploymentproperties
WHERE columnname = 'ADWebApplicationRootdomain'

Ensure the NVarCharColumn column shows the correct URL, else it can be fixed with the following statements (replace server and port with the appropriate values):

UPDATE DeploymentProperties SET 
        NVarCharColumn = '<server>:<port>'
WHERE ColumnName = 'AsyncSdkRootdomain'

UPDATE DeploymentProperties SET 
        NVarCharColumn = '<server>:<port>'
WHERE ColumnName = 'ADSdkRootdomain'

UPDATE DeploymentProperties SET 
        NVarCharColumn = '<server>:<port>'
WHERE ColumnName = 'ADWebApplicationRootdomain'