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;