Kids, don't try this at home!
Tips & Tricks for C#, ASP.NET and CRM
-
Open Sesame! - Dynamics CRM 2011 Solution File
I like breaking into things to see what they look like on the inside, on a rainy day like today with not much to do I decided to see what the solution export file is made of.
-
A bit of syntatic sugar for CRM 2011 LINQ
We've been using XrmLinq for our CRM 4 developments and we've gotten use to that syntax, the new LINQ provider in CRM 2011 is a bit different but thanks to extension methods and generics we can make it look the same as XrmLinq. Main reason for this is to port existing code over to CRM 2011 with minimal efforts.
-
5 syntax changes in Dynamics CRM 2011 plugins
There are number of changes between Dynamics CRM 2011 SDK and CRM 4 SDK. Let’s take a look at what has changed between plugins.
-
How to change the grid icons dynamically
Here is an unsupported but a harmless customisation you can do to Dynamics CRM in-order for you to change the grid icons dynamically. In the example above I wanted to show whether an account has been locked or not (keep an eye out for my next blog post on how you can set privacy settings on records/child records per user and per role)
The standard grids in Dynamics CRM has a css class defined called "ms-crm-List-Data", if you have a look at the /_grid/AppGrid.css.aspx you'll see that, that class has a behaviour defined, this is what we'll use to swap out the icon.
For example
.ms-crm-List-Data
{
table-layout: fixed;
width: 100%;
behavior: url(/_static/_grid/appgrid_defaultdata.htc) url(/isv/magnetism/project/swapicon.htc);
}
Highlighted in bold is our custom behaviour script, which looks something like this:
<public:component lightweight="true">
<public:attach event="ondocumentready" onevent="initSwapIcon()"/>
<script language="JavaScript"></script>
<script type="text/javascript">
function initSwapIcon() {
// only apply it to known entities + xyz crm
if (typeof (this.oname) != "undefined" && window.location.href.toLowerCase().indexOf("xyz") > 0) {
if (this.oname != "1") { return; } // 1=account
for (var i = 0; i < this.rows.length; i++) {
if (typeof (this.rows[i].oid) != "undefined") {
this.rows[i].cells[1].innerHTML = "<img src=\"" + "/isv/magnetism/project/swap-icon.ashx?id=" + this.rows[i].oid + "&type=" + this.oname + "\" />";
}
}
}
}
</script>
</public:component> -
Pre-filter the Dynamics CRM Form Assistant
Time for another trick...
While trying to reduce as many clicks as possible one customer insisted that they want the form assistant pre-filtered, most of you are aware that this is not supported.GoogleBing said it's unsupported and I couldn't see any useful info so opened up the IE Dev Toolbar and found that there are 2 elements; a textbox for searching via form assistant and the search icon (findValue and btnGo), now all that's needed is to put our pre-filtering text into it and force click that button!
On the form onLoad event -
Dynamics CRM 4 Rollup 8, Rollup 9 Error + Fix
Cannot insert the value NULL into column 'InvoiceNumber', table
This happened recently on a hosted server, just for fun I thought I'd see if I can find the sql script that's doing it. -
Dynamics CRM 4 Recurring Tasks
Time for another crm goodie...
Here's a quick and dirty way of making tasks recur in dynamics crm using couple of attributes and a workflow! -
Programmatically reuse Dynamics CRM 4 icons
The team that wrote the dynamics crm sdk help rocks!
I wanted to display the same crm icons on our time tracking application for consistency, so I opened up the sdk help file, searched for 'icon', ignored all the sitemap/isv config entries since I know I want to get these icons programatically, about half way down the search results I see 'organizationui', sure enough that contains the 16x16 (gridicon), 32x32 (outlookshortcuticon) and 66x48 (largeentityicon) icons!
To get all the entities, execute a retrieve multiple request.
RetrieveMultipleRequest request = new RetrieveMultipleRequest
{
Query = new QueryExpression
{
EntityName = "organizationui",
ColumnSet = new ColumnSet(new[] { "objecttypecode", "formxml", "gridicon" }),
}
};
var response = sdk.Execute(request) as RetrieveMultipleResponse;
Now you have all the entities and icons, here's the tricky part, all the custom entities in crm store the icons inside gridicon, outlookshortcuticon and largeentityicon attributes, the built-in entity icons are stored inside the /_imgs/ folder with the format of /_imgs/ico_16_xxxx.gif (gridicon), with xxxx being the entity type code. The entity type code is not stored inside an attribute of organizationui, however you can get it by looking at the formxml attribute objecttypecode xml attribute.
response.BusinessEntityCollection.BusinessEntities.ToList()
.Cast<organizationui>().ToList()
.ForEach(a =>
{
try
{
// easy way to check if it's a custom entity
if (!string.IsNullOrEmpty(a.gridicon))
{
byte[] gif = Convert.FromBase64String(a.gridicon);
}
else
{
// built-in entity
if (!string.IsNullOrEmpty(a.formxml))
{
int start = a.formxml.IndexOf("objecttypecode=\"") + 16;
int end = a.formxml.IndexOf("\"", start);
// found the entity type code
string code = a.formxml.Substring(start, end - start);
string url = string.Format("/_imgs/ico_16_{0}.gif", code);
Enjoy!
-
Tax rules for Dynamics CRM 4
Now that Tax (G.S.T) is about to change here in New Zealand it's probably a good time that you check with your dynamics crm implementor/developer if you're going to get pinged for changing 12.5% to ...
We've created an addon for dynamics crm that automatically calculates tax. It works on any entity (even custom ones), you can specify different rates, different rates for different currencies and/or combinations of both on any entity as long as there is an amount and a tax field.
For example, take a look at the screenshot below, we've configured the tax rules plugin to run on an invoice line item.
Future proof your dynamics crm by contacting us and installing this plugin! -
CRMAppPool number of worker processes and plugins
I recently came across some strange behaviour in dynamics crm. It seems that if you increase the number of worker processes from 1 (default) to n and you have plugins running synchronously crm will throw access denied exceptions randomly when the load is high on the server.
Unhandled Exception: *.CrmException:
0x80048405
Access is denied.
Platform
What seems to happen is a request comes into crm, it fires a plugin then when the plugin tries to make another call to crm (using context.CreateCrmService()) it fails, the reason I believe is this request gets routed through a different w3wp which is a whole different app domain.
Workaround
Keep the worker process count at 1 on the CrmAppPool