Technical Fun

Archive for the ‘Rambling’ Category

Holla holla, CRM Party dudes, it’s me again in a very mundane snippet series of CRM 4.0.
This time, we’re gonna grab the content from a picklist attribute and show it to the world! (Well, usually they end up only seeing an web app, but whatever ..)

Beware, this one’s an overkill scenario, the essence is somewhere within. Seek. 🙂

First things first, I like to create an interface that should build the structure of a picklist object (Why? because .. just because).

1 interface IPicklistObject 2 { 3 int Id {get; set;} 4 string Name {get; set;} 5 }

Then, if an entity got many picklist attributes, we’ll create each class that implement that interface, just like that. (i.e: This SeverityLevel class below).

1 public class SeverityLevel : IPicklistObject 2 { 3 4 #region IPicklistObject Members 5 6 public int Id 7 { 8 get; 9 set; 10 } 11 12 public string Title 13 { 14 get; 15 set; 16 } 17 18 #endregion 19 }

Further more, if you have many picklist-type attributes on your entity, you might want to do mapping externally. My method of choice was a custom xml file that holds to map, like this:
(We’ll need this to pass to the Activator later ..[why??? sshhh ….!])

1 <configuration> 2 <settings> 3 <attributeName> 4 <severitylevel>Full.Name.Of.Your.Concrete.Class.SeverityLevel</severitylevel> 5 </attributeName> 6 </settings> 7 </configuration>

<severitylevel> tag is actually the name of the picklist attribute in crm.
Well of course as a bonus snippet, here’s what I do to read this XML;

1 private static string getMappedValueOf(string attributename) 2 { 3 XmlDocument xDoc = new XmlDocument(); 4 string sFileName = YOUR_XML_FILE_LOCATION; 5 6 if (File.Exists(sFileName) == false) 7 { 8 return string.Empty; 9 } 10 11 try 12 { 13 xDoc.Load(sFileName); 14 XmlNode theNode = xDoc.SelectSingleNode("/configuration/settings/attributeName/" + attributename); 15 if (theNode != null) 16 return theNode.InnerText; 17 18 xDoc = null; 19 return string.Empty; 20 } 21 catch 22 { 23 xDoc = null; 24 } 25 26 return string.Empty; 27 }

Ok, if you are somewhat still following this guide [ I really have no idea why you do that ], you will need to create this method;

1 private static IPicklistObject CreateFrom(string attributename, int key, string name) 2 { 3 Type atttype = Type.GetType(getMappedValueOf(attributename.ToLower()), false); 4 IPicklistObject result = (IPicklistObject)Activator.CreateInstance(atttype); 5 6 result.Id = key; 7 result.Title = name; 8 9 return result; 10 }

Last and final thing, a method that will fetch the picklist attribute using the metadata service (if you’re not like me, this should be the only part you read).

1 public static IList<IPicklistObject> getPickListValue(string entityName, string pickListAttributeName) 2 { 3 RetrieveAttributeRequest attributeRequest = new RetrieveAttributeRequest(); 4 attributeRequest.EntityLogicalName = entityName; 5 attributeRequest.LogicalName = pickListAttributeName; 6 attributeRequest.RetrieveAsIfPublished = true; 7 8 RetrieveAttributeResponse attributeResponse = 9 (RetrieveAttributeResponse)metaService.Execute(attributeRequest); 10 11 PicklistAttributeMetadata pl = 12 (PicklistAttributeMetadata)attributeResponse.AttributeMetadata; 13 14 IList<IPicklistObject> resultset = new List<IPicklistObject>(); 15 16 foreach (Option o in pl.Options) 17 { 18 resultset.Add(CreateFrom(pickListAttributeName,o.Value.Value,o.Label.UserLocLabel.ToString())); 19 } 20 21 return resultset; 22 }

So at this point, you can just pass this collection of picklist object to a control, (a drop down list in my case), and be happy.


Holla, CRM Party people, to entertain your greed towards CRM snippets and to keep me from forgetting such a trivial thing, here we go … the adding attachment / note / annotation snippet for CRM 4.0. (In this sample I am binding it to the incident entity).

1 public static bool AddAttachment(string filename, Guid incidentguid, byte[] modal, out string errormessage) 2 { 3 try 4 { 5 string encodedData = Convert.ToBase64String(modal); 6 7 annotation ano = new annotation(); 8 ano.filename = filename; 9 ano.isdocument = new Petrosea.CRM.SD.MetaUtility.CRMWebService.CrmBoolean(); 10 ano.isdocument.Value = true; 11 ano.documentbody = encodedData; 12 ano.mimetype = "application/octet-stream"; 13 ano.objectid = new Lookup(); 14 ano.objectid.type = EntityName.incident.ToString(); 15 ano.objectid.Value = incidentguid; 16 ano.objecttypecode = new EntityNameReference(); 17 ano.objecttypecode.Value = EntityName.incident.ToString(); 18 19 TargetCreateAnnotation target = new TargetCreateAnnotation(); 20 target.Annotation = ano; 21 CreateRequest createrequest = new CreateRequest(); 22 createrequest.Target = target; 23 CreateResponse created = (CreateResponse)crmService.Execute(createrequest); 24 25 errormessage = String.Empty; 26 return true; 27 } 28 catch (Exception ex) 29 { 30 errormessage = ex.Message; 31 return false; 32 } 33 }


Holla, Ok, I am new to the world of CRM 4.0 Plug-Ins, and even though I wrote many callouts for CRM 3.0, that does not count to the experience. So, I am a flat newbie 🙂 [excuse mode ON].

Here’s the story; I was trying to hook to a post update event of the opportunity entity, and naturally wanting to do something based on the opportunityid I (should have) obtained easily.

Here’s the un-easy part;

Microsoft.Crm.Sdk.DynamicEntity opp = context.PostEntityImages["opportunity"] as Microsoft.Crm.Sdk.DynamicEntity;

and afterwards, I could call the Id (GUID) of the opportunity like this;

Microsoft.Crm.Sdk.Key okey = opp["opportunityid"] as Microsoft.Crm.Sdk.Key; Guid oppid = okey.Value;

Hmm… before I got here, I tried to use and register PreEntityImages, but failed. I tried to use OutputParameters of the context, and failed as well.

So, for post events, I’ll stick to this PostEntityImages thing.


Well, not exactly removing, just crippling it so it won’t function. Hahah…

It all began with a guy in another department who got this persistent demand of getting rid of the single file upload button from a SharePoint document library upload menu. “We can upload single file from the multiple one, no need to have a single one.” He claimed. Hahah..

Given that I am a world-class-lazy-bum, I googled, but found that some working solutions applied globally towards the entire site collection, and not strictly to one doclib inside one site. Some claimed they have managed to do so by doing various tricks. But again, due to my acute laziness, I decided not to play around with Features, or even those object models, instead, I resorted to JavaScript.

What I did was described in Lazy 101; detect the Upload Menu by it’s many possible identifier (in this case i use its’ “text” attribute), and brutally disabled it. I cunningly inserted a content editor webpart in the page where the doclib tool bar was visible, and chuckled in an insane glee. Mwhuahahahhahuahahahah …

The script is as below:

<script type="text/javascript"> function GetElementByText(tagName, title) { var a = document.getElementsByTagName(tagName); for (var i=0; i < a.length; i++) { if (a[i].text) { if (a[i].text === title) { return a[i]; } } } return null; } if (window.onload) { var oLoad = window.onload; window.onload = function bodyLoad() { oLoad(); var o = GetElementByText("ie:menuitem","Upload Document"); if (o) { o.disabled = true; } } } </script>

[Update] Hey, guess what, a very kind guy has created a better tool for this (he’s even “featurize” it), check it here

I got an XML document that looks like this.

<Area id=”1″>
<name>Brave Land</name>
<description>An area where the brave may live forever</description>

Now, if I want to search and fetch the text inside the “name” tag based on a supplied “id”, I can rely faithfully on LINQ.

XDocument doc = XDocument.Load(PATH_TO_XML_DOCUMENT);
var x = from area in doc.Descendants(“Area”)
          where (int)area.Attribute(“id”) == MY_SUPPLIED_ID
          select (string)area.Element(“name”);

and consume it using x.First()

aaah …. how readable, how lovely, Nirvana!!!

Being an information worker is fun, and full of technology hiccups.
This blog aims to share all of those in forms of short postings, or probably if I got bored enough, I will write those things in a form of poem, song, or whatever i can pull out then.
So watch out for MOSS, CRM, and regular .Net trivias, eurekas, and mamamias here.

Over and out now.