Wednesday, September 1, 2010

FetchXml and the current user

I'm adding this because I can never remember how to do this...  Every once in a while I have to execute a fetchXml statement that has to use the current userId as part of the filter.  Here's how you do it:

<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
    <entity name='neu_lastopenedobject'>
        <attribute name='neu_contactid'/>
        <attribute name='neu_lastopenedobjectid'/>
        <filter type='and'>
            <condition attribute='ownerid' operator='eq-userid'/>
        </filter>
    </entity>
</fetch>";

Note the 'condition' node.  We're able to filter against the current user by using the operator='eq-userid' attribute.  Microsoft has all of this documented somewhere...

Caleb

Saturday, August 28, 2010

Resizing a CRM form.

I was asked recently to increase the 'y' axis of a CRM form (it's just a html window).  Here's a real easy way to do it:

window.resizeby( 10, 10 ); 
/*window.resizeBy(x,y)*/

This handy JavaScript function will increase the size of the 'x' and 'y' axis by 10 pixels each.

Hiding a memo field on a CRM form

So I was working away the other day and got a request to hide a memo field on a CRM form.  This is a little bit more complex than just setting the display or visible style attribute.  Here's how it's done:


/*hide memo field*/
document.getElementById("neu_viewstartext_c").style.display = "none";
document.getElementById("neu_viewstartext_d").style.display = "none";
var parentTr =document.getElementById("neu_viewstartext").parentNode.parentNode;
var tr = parentTr.nextSibling;
for(var x = 0; x<3; x++) {/*hide*/
    tr.height = "1";
    tr= tr.nextSibling;/*Assign to sibling*/
}
for(var x = 0; x<3; x++) {/*show*/
    tr.height = "25";
    tr= tr.nextSibling;/*Assign to sibling*/
}

Thursday, August 19, 2010

CRM 4.0 and PostRetreivePlugins

Hello Gang,

Ran into an interesting issue today. I had a client that needed to process some data before the form was displayed to the user. So we decided to use the PostRetreive message. We found that the message only returns properties that are on the form. So if you want to examine a property that isn't on the form you're most likely (I haven't tried this yet) going to have to add a pre image to the step.

Happy coding...

Wednesday, August 18, 2010

CRM 4.0 on 64 bit platform.

I was coding away the other day and ran into a real interesting problem. Here's the result of trying to create the CrmService object on a Window 2008r2 server:

System.InvalidOperationException: Unable to generate a temporary class (result=1).
error CS0001: Internal compiler error (0xc00000fd)
error CS0003: Out of memory

at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer.GetSerializersFromCache(XmlMapping[] mappings, Type type)
at System.Xml.Serialization.XmlSerializer.FromMappings(XmlMapping[] mappings, Type type)

This error message initially made me think that there was some permissions issue with the ASPNET user not being able to write to temp. That was not the case. I solved the problem by using sgen to create a .XmlSerializers.dll file. There was some issues with sgen not being able to handle spaces in the path to the key file. So I put everything needed into the same directory and ran sgen. Here's the parameters that I used:

sgen /compiler:/keyfile:keyfile.snk /p [offending].dll

Here's a link to sgen.

Have fun...

Thursday, August 5, 2010

Here's some code (c#) to test for a GUID using a regular expression:

Regex isGuid = new Regex(@"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$", RegexOptions.Compiled);
if (isGuid.IsMatch(owner))
{
ownerId = new Guid(owner);
}

Have fun...

Tuesday, August 3, 2010

Some useful regular expressions

Every once in a while I'm asked to do some JavaScript form validation. Here's a handful of regular expressions that I use:

  • SSN: var filter = /^\d{3}-\d{2}-\d{4}$/;
  • TIN: var filter = /^\d{2}-\d{7}$/;
  • Date: var filter = /^(?=\d)(?:(?:(?:(?:(?:0?[13578]|1[02])(\/)31)\1|(?:(?:0?[1,3-9]|1[0-2])(\/)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})|(?:0?2(\/)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:(?:0?[1-9])|(?:1[0-2]))(\/)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})))?$/; // ($|\ (?=\d)))?(((0?[1-9]|1[012])(:[0-5]\d){0,2}(\ [AP]M))|([01]\d|2[0-3])(:[0-5]\d){1,2})?$/;

I'll add to this list as needed...

Happy coding.

Thursday, July 22, 2010

Figure out what element fired the a function

Hello Gang,

Every once in a while I'll write a JavaScript function that is generic; it can handle requests from several different form elements. The function needs to know what element fired it. Here's how to figure that out:

    if(!e) {e = window.event;}
var element = e.srcElement;
Now that you nave the 'element' object you can now reference it via the 'crmForm' object.

 crmForm.all[element.id].DataValue

Get busy!

Thursday, June 24, 2010

Crm 4.0 timeouts with large custimization imports

The fellows at Microsoft have a great write up on some ideas to try to resolve this problem. See this link.

Nice work Microsoft!

Dynamically load JavaScript file

Hello Gang,

Recently I needed to figure out how to load a JavaScript file into the DOM during the onload event. I was working with a form in CRM 4.0 and was tired of cutting and pasting the same .js code. Here's how I did it:

/*Load script for ajax calls*/
var scriptLoaded = false;
var TIMER= 0;

crmForm.Neudesic_LoadScript = function(scriptToLoad) {

var head= document.getElementsByTagName("head")[0];
var script= document.createElement("script");
script.type= "text/javascript";
script.src= scriptToLoad;
head.appendChild(script);
/*make sure the script gets loaded before it gets called*/
script.onreadystatechange= function () {
if (this.readyState == "complete" || this.readyState == "loaded") {
scriptLoaded = true;
}
}
}
crmForm.Neudesic_IsScriptLoaded = function() {
if(scriptLoaded) {
clearInterval (TIMER);/*this will stop the loop*/
}
return(scriptLoaded);
}

Here's the code for calling it:
if(crmForm.FormType == 1 || crmForm.FormType == 2) {
/*load script*/
crmForm.Neudesic_LoadScript("/ISV/neudesic/clarify/DCA/JavaScript/ajax.js");
/*check to see if script is loaded*/
TIMER = setInterval ("crmForm.Neudesic_IsScriptLoaded()", 500);
}
Here's a great link for more information on this topic. It covers writing some JavaScript that could do this for multiple files. Basically you need to include some arrays that hold the TIMERs and the URLs that need loaded.

Have fun,

Caleb

Thursday, June 3, 2010

Hiding tabs in CRM 4.0

Here's how you hide a tab on a CRM 4.0 form.

Define the function to hide the tab (place in the form's onload event):

/*hide tab*/
crmForm.Neudesic_HideTab = function(tabName) {
document.getElementById(tabName).style.display = "none";
}
Now call the function from the onload event of the form:

if(crmForm.FormType == 1 || crmForm.FormType == 2) {
/*hide tab*/
crmForm.Neudesic_HideTab("tab4Tab");
}
The tabs across the top of the form have the following naming convention: tabXTab where X is the number of the tab (starting with zero). So if you wanted to hide the first tab you would use tab0Tab as the name. If you wanted to hide the second tab you would use tab1Tab, etc.

Have fun...

Tuesday, June 1, 2010

Setting Crm 4.0 object attributes to null

Just got a call from a client on how to do this. CRM 4.0 attributes need to have to properties set:
  1. IsNull
  2. IsNullSpecified

CrmDateTime dt = new CrmDateTime();
dt.IsNull = true;
dt.IsNullSpecified = true;
CrmMoney cm = new CrmMoney();
cm.IsNull = true;
cm.IsNullSpecified = true;

Happy coding...

Thursday, May 27, 2010

Collapse Sections in CRM 4.0

Here's some code that will collapse sections on CRM 4.0.


/*Function figures out if id of element is a GUID.  Useful for collapsing sections*/
crmForm.DC_IsGUID = function(expression)
{
if (expression != null)
{
var pattern = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/;
return(pattern.test(expression));
}
return false;
}

crmForm.DC_ToggleSection = function(element, open) {
while(!crmForm.DC_IsGUID(element.id)) {
element = element.parentNode;
}
if(open) {
element.style.display = "block";
}
else
{
element.style.display = "none";
}
}


Happy coding...

Tuesday, May 4, 2010

Retrieving the org name from the URL string

I was just getting ready to write some JavaScript code to parse the org name out of the URL string when I decided to see if someone else had already written the code. I was digging around on Google when I found this function: prependOrgName(). The function is one of the global functions inside CRM. See this link.

Nice work Microsoft!

Tuesday, April 27, 2010

CRM 4.0 and supported databases

So... Remember how I said that this blog was a place for me to stick data that I'm always forgetting? Here's a great link that talks about what database versions CRM 4.0 supports...

http://technet.microsoft.com/en-us/library/dd979170.aspx

Good times will be had!

C

Tuesday, March 16, 2010

FetchXml and the Paging Cookie

So the other day I was trying to extract some data from a CRM live instance. I needed to get more than 5000 records and I was trying to query a many to many relationship table. So I had to use fetchXml as the QueryExpression class can't query a many to many table. To get more than 5000 records I had to enable paging via the paging cookie. Here's how it's done:



// Build fetchXml string with the placeholders.
String fetchXml = @"<fetch version='1.0' mapping='logical'
page='{0}' count='100' paging-cookie='{1}'>
<entity name='neu_neu_settlement_payees'>
<attribute name='neu_neu_settlement_payeesid' />
<attribute name='neu_settlementid' />
<attribute name='contactid' />
</entity>
</fetch>";

fetchXml = String.Format(fetchXml, pageNumber, pagingCookie);

// Excute the fetch query and get the xml result.
String fetchResult = crmService.Fetch(fetchXml);
// Load the fetch result into XMLDocument to parse its cotents.
XmlDocument doc = new XmlDocument();
doc.LoadXml(fetchResult);
// The morerecords attribute will return 1 if there are more records.
String moreRecords = doc.DocumentElement.Attributes["morerecords"].InnerText;

// The paging-cookie attribute holds the paging cookie to pass in the next query.
XmlAttribute at = doc.DocumentElement.Attributes["paging-cookie"];
pagingCookie = (at != null) ? at.InnerXml : string.Empty;

// Retrieve the result nodes.
XmlNodeList resultNodes = doc.DocumentElement.SelectNodes("result");

// Check for morerecords, if it returns 1.
if (moreRecords != null && moreRecords == "1")
{
// Increment the page number to retrieve the next page.
pageNumber++;
}
else
{
// If no more records in the result nodes, exit the loop.
break;
}

The big stumbling block for me was using .InnerXml to get the pagingCookie value; not .InnerText. This code all sits in a while(true) loop.

Have fun...

Java and Regular Expressions

So the other day I was working away with some open source bits and was needing to do some string parsing. I am a hugh fan of regular expressions. They are vary efficient; and once understood, make it vary easy to perform complex string parsing with very few lines of code. I was trying to perform matching on special regular expressions characters; namely '?.' I was trying to escape the ? with black slashes. In the java world you have to use two black slashes for every one that you want. So '\\' turns into '\' and '\\\\' translate into '\\.' After spending a while trying to escape the ? I found a very simple solution. Just add the "Pattern.LITERAL" flag to the Pattern constructor. Here's an example:


Pattern pattern = Pattern.compile(name,Pattern.CASE_INSENSITIVE | Pattern.LITERAL);



Happy coding...

Tuesday, March 2, 2010

Retrieving the total number of records for a given object

I'm currently working on a CRM 4.0 live deployment. I needed to figure out how many of a given object existed in the CRM database. On an on-premise version of CRM this is a simple problem to solve. You can use SSRS or just query the database directly. In CRM 4.0 live this isn't so easy. Query Expression will only return 5000 results with a single query. I had to use fetch xml with the 'aggregate' attribute. Here's the needed fetch xml:

String fetchXml = @"<fetch version='1.0' output-format='xml-platform'
mapping='logical' aggregate='true'>
<entity name='@ENTITY_NAME'>
<attribute name='@KEY' aggregate='count' alias='total' />
@FILTER
</entity>
</fetch>";

Here's the code:
/*Loop through objects and retreive totals*/
foreach (String entityName in objects)
{
System.Console.Write("Retreiving " + entityName);
String fetchXml = @"<fetch version='1.0' output-format='xml-platform'
mapping='logical' aggregate='true'>
<entity name='@ENTITY_NAME'>
<attribute name='@KEY' aggregate='count' alias='total' />
@FILTER
</entity>
</fetch>";

fetchXml = fetchXml.Replace("@ENTITY_NAME", entityName);
String filter = String.Empty;
if (entityName.Equals("task"))
{
fetchXml = fetchXml.Replace("@KEY", "activityid");
}
else
{
fetchXml = fetchXml.Replace("@KEY", entityName + "id");
}
if (entityName.Equals("customeraddress"))
{
filter = "<filter type='and'><condition
attribute='name' operator='eq'
value='Historical'/></filter>";
}

fetchXml = fetchXml.Replace("@FILTER", filter);

String xml = String.Empty;

xml = crmService.Fetch(fetchXml);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
//Retrieve count
int total = Convert.ToInt32(xmlDoc.GetElementsByTagName("total")[0].InnerText);
System.Console.Write(": total: " + total + "\n");
}

See this Microsoft link for more information.

Bits, bits, they encircle and enslave... I can't escape!

C

Monday, March 1, 2010

Hide left hand nav links

Hello Gang,

This post is about hiding left hand nav links. Every once in a while I get asked to hide certain navigation links based on user interaction or values on a form. Here's the process:

  1. Identify the DOM element that we need to hide
  2. Create function to toggle DOM element
  3. Fire function when the form loads
To find the element id that we need to hide you can do one of two things:
  1. Find the relationship name in the relationship section of the customizations editor. You will have to prefix "nav_" to this relationship name
  2. Open the form in question, press Ctrl-n, and dig around in the source until you find the appropriate DOM element id.
Here's the code:



crmForm.Neudesic_HideNavObligor = function() {

/*get value of checkbox*/
var value = crmForm.all.neu_obligor.DataValue;
var display = "none";
if(value) {
display = "block";
}
try {
/*this will fail on preview as the left hand menu is not generated*/
var element = document.getElementById("nav_neu_obligor_neu_settlement");
element.style.display = display;
}catch(error) {

}
}
/*attach event*/
if(crmForm.FormType == 1 || crmForm.FormType == 2) {

crmForm.all.neu_obligor.attachEvent("onclick", crmForm.Neudesic_HideNavObligor);
/*fire event when the form opens*/
crmForm.Neudesic_HideNavObligor();
}

Saturday, February 27, 2010

Running a 32 bit command line app on a 64 bit platform

So I am currently working on a data migration into CRM 4.0 live. The various wrappers and libraries for the solution require that the executable run as a 32 bit application. To solve this problem do the following:

  • Start->Run
  • %windir%\SysWoW64\cmd.exe
This will open up a command prompt that utilizes the Windows-32-on-Windows-64 (WOW64) subsystem layer to run 32-bit programs.

There is an excellent post here with lots more details.

Music and passion...

Friday, February 26, 2010

Using Advanced Find to generate FetchXml

This post doesn't contain anything original. I stole this from here (good ones borrow, great ones steal). Here's how you use the Advanced Find functionality in CRM to create proper fecthXml.

  • Open advanced Find and press Ctrl-n. This will open Advanced Find in a separate window that gives you access to the browser bar
  • Define your query
  • Execute the query
  • Paste the following into the address/url bar in the browser:
    javascript:alert(resultRender.FetchXml.value); -- This will cause a javascript alert to pop up and display your fetchxml
Props to Ronald Lemmen for this excellent tip.

I just found another bit of of JavaScript that can assist you with this:

 javascript:void( new function(){ prompt("Fetch Parameters:",getFetchParams());function getFetchParams(){ return "FetchXml:\n" + advFind.FetchXml + "\n\n" + "LayoutXml:\n" + advFind.LayoutXml + "\n\n" + "EntityName:\n" + advFind.EntityName + "\n\n" + "DefaultAdvancedFindViewId:\n" + advFind.DefaultAdvancedFindViewId } } ) 


Thanks to Adi Katz for this great tip!


Happy coding!

Wednesday, February 24, 2010

View child objects in Iframe

This is a post for my benefit as I can't seem to remember anything. Here's the JavaScript code to display child objects of CRM object in an iframe.

  1. Create Iframe
  2. Modify onload event to populate iframe
  3. Make css changes to iframe to get rid of the white space around the iframe
Here's the code:

  var iframe = crmForm.all.IFRAME_AttorneyFees;
var url = "/UserDefined/areas.aspx?oId="+crmForm.ObjectId
+"&oType="+crmForm.ObjectTypeCode+"&security=852023&tabSet=neu_lawfirm_neu_attorneyfee";
iframe.src = url;

/*clean up css. Makes the iframe look lots better*/
iframe.onreadystatechange = function() {

if(iframe.readyState != 'complete' )
{
return;
}
/*Change the background color*/
iframe.contentWindow.document.body.style.backgroundColor = "#eef0f6";
/*Remove the left border*/
iframe.contentWindow.document.body.all(0).style.borderLeftStyle = "none";
/*Remove padding*/
iframe.contentWindow.document.body.all(0).all(0).all(0).all(0).style.padding = "0px";
/*Make the cell the full width of the IFRAME*/
iframe.contentWindow.document.body.all(0).style.width = "102%"
}

The tabset variable in the url variable needs to be the name of the relationship to the child object. You can find this information in the relationships (left hand side of the customize entity form). You have to change the iframe variable to point to the iframe that you are pointing at. You can find this by using the customizations editor->iframe->Name.

Tuesday, February 23, 2010

Dynamic tabs in a CRM form

This post doesn't cover any new ground. This topic has been covered in other blog posts. But I'm tired of digging up these other sites as I can't remember anything. The goal of this post is to explain how to toggle the display of a tab on a CRM form. We need to accomplish the following:

  • Create function to toggle tag
  • Call function when the form is loaded
  • Call function when element is clicked on

Let's create the function (onload):

/*Create function to hide tab*/
crmForm.Neudesic_ToggleLawfirmTab = function() {

/*check the value of the checkbox*/
var value = crmForm.all.neu_lawfirm.DataValue;
if(!value) {
crmForm.all.tab2Tab.style.display = "none";
} else {
crmForm.all.tab2Tab.style.display = "block";
}
}

Now let's take care of the last two issues:


if(crmForm.FormType == 1 || crmForm.FormType == 2) {
/*make sure the proper tabs are displayed*/
crmForm.Neudesic_ToggleLawfirmTab();

/*attach custom function to new_lawfirm element.
The CRM onchange event doesn't fire until the checkbox element
losses focus. I don't like this. So let's attach the event*/
var element =
document.getElementById("neu_lawfirm")
element.attachEvent("onclick", crmForm.Neudesic_ToggleLawfirmTab);
}

There you go! A couple discussion points. I don't like using the onchange event handler that CRM exposes for checkboxes as it doesn't fire until the element looses focus. So I use attachEvent to get the function to fire. Note that you can also use element.onclick. However this will override any other JavaScript functions that are attached to the element in question. Not really the best approach; especially when working with other developers. Also note that the toggle function is a child of the crmForm object. This allows for the function to be called in a onchange event from another CRM form onchange/onsave event. Defining as a free standing function will cause scope to be lost in another onchange/onsave event.

Keep in mind that in CRM 5.0 form tabs are going away. So this code will not work; but that doesn't matter now does it? Your technical; act like it. Solve the problem when it appears and know that it's coming. In the meanwhile you customers/users now have one more reason to love you...

Happy coding!

First post!

I'm done digging through piles of code to find some obscure solution that, at one point in time, I was very proud of but have now forgotten. The primary focus of this blog will be around technical solutions for Microsoft CRM. However, I reserve the right to ramble into the open source world from time to time and to shamelessly promote my band, Black Mercies; as well as make money from your visits to this site.

I hope you find this useful and entertaining...

Ones and Zeros,

Concrete and collapse

Your high priest to the Gods of technology... Sacrifices are accepted.