July 16, 2009

Show custom notifications on Microsoft Dynamics CRM - upgrade

Marco Amoedo created cool javascript function that displays custom warning messages in Microsoft Dynamics CRM 4.0. http://marcoamoedo.com/blog/show-custom-warning-messages-on-microsoft-dynamics-crm/

I liked the idea so much, that I took the script and upgraded pimped it.

What it does?

The function simply adds a notification on top of the form, like in the picture below.

image

You can add multiple notifications with different icons.

image

Update or delete previously added notifications or add new ones. This image shows (after Name onChange event) changed error text, updated third notification to info style and a new warning. Compare it with previous picture.

image

How to use it?

Step 1: Insert this code into form OnLoad event.

/*============== addNotification function =============






Adds a message on the top of the entity form using



the same visual style as Microsoft CRM.



If function is called more than once,



the messages are added at the bottom of the list



If the message with same ID already exists,



then the message is updated and not added to a list.



It also supports deleting of previously added notifications.






Put this function in the OnLoad event,



so you can use it in all form and field events.






Parameters:



message - message to be shown to the user



messageType - Type of the message: 1 - critical, 2 - info, 3 - warning



notificationId - ID of the notification (needed for updating purposes)



    



Created by:



Marco Amoedo (http://marcoamoedo.com) - the idea and initial function



Dejan Dular (http://a-crm.blogspot.com) - upgraded functionality (different icons, updating and deleting notifications)



    



=======================================================*/



 



addNotification = function(message, messageType, notificationId)



{



    var notificationsArea = document.getElementById('Notifications');



    



    if (notificationsArea == null)



    {



        //Don't display message when deleting a notification.



        if (messageType != 4)



        {



            //Sorry. Notifications are not possible on this form.



            //Display a message box instead of notification.



            alert(message);



        }



        return;



    }



    



    var notificationDIV = document.getElementById('NotificationDiv_' + notificationId);



    



    //Delete the notification



    if (messageType == 4)



    {



        if (notificationDIV != null)



        {



            //Remove the notification



            notificationsArea.removeChild(notificationDIV);



        }



        return;



    }



    



    //Get the notification image. The default is info image.



    var notificationImage;



    switch (messageType)



    {



        case 1:



            notificationImage = '/_imgs/error/notif_icn_crit16.png';



            break;



        case 2:



            notificationImage = '/_imgs/error/notif_icn_info16.png';



            break;    



        case 3:



            notificationImage = '/_imgs/error/notif_icn_warn16.png';



            break;    



        default:



            notificationImage = '/_imgs/error/notif_icn_info16.png';



    }



 



    //Create notification



    var notificationTable = '<TABLE cellSpacing="0" cellPadding="0"><TBODY><TR><TD vAlign="top"><IMG class="ms-crm-Lookup-Item" alt="" src="' + notificationImage + '" /></TD><TD><SPAN>' + message +'</SPAN></TD></TR></TBODY></TABLE>';



    



    //Check if the notification with same ID already exists



    if (notificationDIV == null)



    {    



        //Create a new notification



        var notificationHTML = '<DIV class="Notification" ID="NotificationDiv_' + notificationId + '">' + notificationTable + '</DIV>';



        notificationsArea.innerHTML += notificationHTML;



        notificationsArea.style.display = 'block';



    }



    else



    {



        //Update the notification.



        notificationDIV.innerHTML = notificationTable;



    }



}



/*============= END addNotification function ===========*/




 



Step 2: Run the following function when there is a need for a notification.




addNotification(string message, int messageType, string notificationId)







Parameters:




  • message – Notification message displayed


  • messageType – Type of the notification (the icon) (1 – critical, 2 – info, 3 – warning, 4 – delete the notification)


  • notificationId – Any string that identifies specific notification. If a function is called later with existing notificationId, the notification will be updated. Otherwise a new notification is added at the bottom of the list. If you want to delete a specific notification, just set messageType = 4 and use correct notificationId.



Thanks again to Marco Amoedo.



 



Originally published by Dejan Dular

March 27, 2009

Reindex whole database

EXEC sp_MSforeachtable @command1="print '?' DBCC DBREINDEX ('?', ' ', 80)"
GO

July 2, 2008

Button that starts a workflow

My client wanted to have a button that starts a specific workflow on the form. So after analyzing some javascript I ended with this code:

var a = new Array(crmFormSubmit.crmFormSubmitId.value);
var sIds = crmFormSubmit.crmFormSubmitId.value+";";
var sEntityTypeCode = "10004"; //Replace this with your entity type code
var sWorkflowId = "{BE7E47C0-2452-4F44-8CCA-425B83A7A8FB}"; //Replace this with your actual workflow ID
var iWindowPosX = 500; //Modal dialog position X
var iWindowPosY = 200; //Modal dialog position Y

var oResult = openStdDlg(prependOrgName("/_grid/cmds/dlg_runworkflow.aspx")+"?iObjType=" + CrmEncodeDecode.CrmUrlEncode(sEntityTypeCode) + "&iTotal=" +
CrmEncodeDecode.CrmUrlEncode(a.length) + "&wfId=" + CrmEncodeDecode.CrmUrlEncode(sWorkflowId)+ "&sIds=" + CrmEncodeDecode.CrmUrlEncode(sIds) , a, iWindowPosX, iWindowPosY);


Of course this is not supported by Microsoft. You use it at your own risk.

June 9, 2008

Generic SQL error

WOW! I'm sooooo happy when I receive such deterministic errors.

After saving an account, this message popped up. And you guessed it - it appeared just SOMETIMES!

After a little of SQL profiling i found the reason:
I extended the account's address1_line1 field from 50 to 100 characters. After saving the account, CRM automatically creates/updates also the customeraddress entity.

Solution:
Extend the customeraddress entity, extend attribute line1, match the length to length of the account address line.

May 30, 2008

Cool SQL query that deletes the duplicates

Found this on Sql Server Central:

CREATE TABLE #new(ID INT NULL, KeyValue VARCHAR(2))
INSERT INTO #new(ID, KeyValue) VALUES (1,'aa')
INSERT INTO #new(ID, KeyValue) VALUES (2,'bb')
INSERT INTO #new(ID, KeyValue) VALUES (1,'aa')
INSERT INTO #new(ID, KeyValue) VALUES (1,'aa')


SELECT * FROM #new;


Now let's delete the duplicates. The semicolon at the beginning is recommended if you are not using it after every SQL sentence. This tells the parser to begin with new statement. Without it you will probably get a syntax error.

;WITH Numbered AS (SELECT RowNo=ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID), ID, KeyValue FROM #new) DELETE FROM Numbered where RowNo>1;

SELECT * FROM #new;


Cleanup...

DROP TABLE #new;

March 3, 2008

Snippet for CRM workflow activity parameter

If you are writing custom workflow activities for workflows in CRM 4.0 you will find this snippet handy.

Copy the code below into a new file and name it CRMParameter.snippet. Save the file into Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets folder. It works in VS2008 too.
The shortcut for the snippet is cwp.

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>CRM workflow property snippet</Title>
<Shortcut>cwp</Shortcut>
<Description>Code snippet for crm property </Description>
<Author>Dejan Dular</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>PropertyInputOutputType</ID>
<ToolTip>Input/output property</ToolTip>
<Default>CrmInput</Default>
</Literal>
<Literal>
<ID>PropertyDisplayName</ID>
<ToolTip>Property display name</ToolTip>
<Default>Display Name</Default>
</Literal>
<Literal>
<ID>PropertyName</ID>
<ToolTip>Property Name</ToolTip>
<Default>name</Default>
</Literal>
<Literal>
<ID>Type</ID>
<ToolTip>Property Type</ToolTip>
<Default>string</Default>
</Literal>
<Literal>
<ID>Class</ID>
<ToolTip>Class</ToolTip>
<Default>ClassName</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[#region $PropertyDisplayName$
[$PropertyInputOutputType$("$PropertyDisplayName$")]
public $Type$ $PropertyName$
{
get { return ($Type$)base.GetValue($PropertyName$Property); }
set { base.SetValue($PropertyName$Property, value); }
}
public static DependencyProperty $PropertyName$Property = DependencyProperty.Register("$PropertyName$", typeof($Type$), typeof($Class$));
#endregion
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>

February 28, 2008

Error at decimal field display format (4.0)

When upgrading a German version of CRM 3.0 to version 4.0, a strange thing happened. All decimal, float or money fields behaved very strange.

Example: User enters a value 2. After clicking save button, the number changes to 200.00 and then immediately to 20.000.00.

Then I noticed that a decimal separator and a thousands separator were the same. Therefore I checked organization settings where everything looked fine.

The problem lied in user settings where both separators were set to dot (.)

SOLUTION:
Change must be made for each user. Set the decimal separator to comma (,).
Update the CRM database to affect all users: UPDATE UserSettingsBase SET DecimalSymbol = ','

January 2, 2008

.NET Compiler bug? (Update)

I have a typed DataTable (called FactTable) that gets data from a table in SQL server where a Date field can be null.

So I have created a System.Nullable variable in my code:
Datetime? emailDate;

And a typed DataRow from my DataTable:
MyDataSet.FactRow factRow = factTable.Rows[0];

Why does this NOT WORK:
emailDate = factRow.IsEmailDateNull() ? null : factRow.EmailDate;

But this works:
if (factRow.IsEmailDateNull())
emailDate = null;
else
emailDate = factRow.EmailDate;



Compiler error is: Type of conditional expression cannot be determined because there is no implicit conversion between '' and 'System.DateTime'

Remember: My variable is nullable!!!

Update:
David defined this problem as a feature. But aren't both examples the same? Isn't this just a compile thing to convert from the first example to the second one?
I think it has to do something with nullable types, because with string or byte[] it works like a charm:
string title = factRow.IsTitleNull() ? null : factRow.Title;
byte[] picture = factRow.IsPictureNull() ? null : factRow.Picutre;

December 14, 2007

Integration of Google maps / Live maps into CRM 3.0, 4.0

I usually don't write about third party solutions, but this one is getting its place in my blog.

A fellow CRM blogger Wolter Kreun from the Netherlands is developing a freeware plugin (Can it be true? A free and very useful plugin for CRM!!!) that fully integrates Google Maps into Microsoft CRM. Soon it will support MS Live maps.

Haven't tried it, but as far as I have seen on the videos it ROCKS!

EDIT (05. oct. 2009): I just have been informed that the link provided below does not work anymore. But you can use similar integration with virtual earth at: http://www.crmwatcher.com/2006/11/virtual-earth-3d-maps-integration-in.html

So chop chop guys and click on this link: http://mscrmgooglemaps.blogspot.com/

November 28, 2007

Computer playing random music

Another post that has absolutely nothing to do with CRM. I just gotta share this.

On channel 9 I found this link to the Microsoft's KB article:
http://support.microsoft.com/default.aspx?scid=kb;en-us;261186


I'm really thinking of installing Windows 95 and crashing the CUP fan. :)