by Daniel Halan
24. June 2010 00:29
When working with Microsoft CRM data-types using web services there is no constructor parameters due to limitations of the WSDL code generation. This leads to few lines of code each time one want to create a variable of any CRM type.
This can be optimized using a Factory class where you encapsle the creation of the desired class. But one even cleaner way is to create a partial class and define "implicit" operators between CRM data-type and .NET data-type.
Here is an example on how it works.
Standard way of assigning a .NET DateTime to CRM DateTime,
CrmDateTime cdt = new CrmDateTime();
cdt.Value = DateTime.Today.ToString("s");
Using implicit declaration,
CrmDateTime cdt = DateTime.Now;
and back,
DateTime dt = cdt;
The code behind this,
public partial class CrmDateTime {
public CrmDateTime(DateTime dt) {
this.Value = dt.ToString("s");
}
public static implicit operator CrmDateTime(DateTime dt) {
return new CrmDateTime (dt);
}
public static implicit operator DateTime(CrmDateTime dt) {
return DateTime.Parse(dt.Value);
}
}
by Daniel Halan
17. December 2009 02:05
Validation of Social Security Number (Personnummer) or the Organisation Number is very common validation when working with business systems, here is a small method to validate the Swedish identification numbers. If you by any chance have done a similar check for your country social security number, would be nice if you post a link to your site or send the code and I will update this post.
IdNrCheck.zip (832,00 bytes)
by Daniel Halan
16. November 2009 23:17
Generics is a very nice feature of C# language, and can be used to simplify the CRM Web Service method calls. One of my responsibilities at Logica is to develop a framework for CRM development, and one of the main classes in this framework is called CrmSystem, it wraps the CrmService methods among other things. Using generics one can then type,
account acc = CrmSystem.Retrieve<account>(myAccountId);
also we use a special NameValue class CrmConditions to one of our Execute overloads, here is how it can look
List<account> acc = CrmSystem.Execute<account>(new CrmCondition("emailaddress1", "daniel@logica.com"));
This would retrieve all accounts that got the email "daniel@logica.com"
Here is one of the overloads for the Retrive Method that uses Generics, it calls an other overload that does the actual call to CRM Web Service using the EntityName string that we get thru typeof(T).Name
public T Retrieve<T>(Guid id, params string[] columnSet) where T : BusinessEntity {
return (T)Retrieve(typeof(T).Name, id, new ColumnSet(columnSet));
}
Hope this gives some inspiration for your own CrmApi wrappers :)
by Daniel Halan
14. September 2009 21:43
Was looking for a standard way of merging two XML Documents using XDocument objects, but found none with duplicate checking. You can use this short snippet bellow to merge two XDocuments, but then duplicate elements will also populate the merged document, so here comes a handy little method that also checks for duplicate items.
Simple Merge (Copy all)
XDocument xdoc =
XDocument.Load("a.xml");
xdoc.Root.Add( XDocument.Load("b.xml").Root.Elements() );
Merge with duplicate element check (C# Class)
HalanTools.zip (0,71 KB)
by Daniel Halan
11. September 2009 23:07
Recently I was working on a dynamic Fetch XML query that was adding a lot of conditions. During a batch run the CRM Service started to crash when the xml size got around ~135kb. My first thought was that there were a size limit of the SOAP message that we'd cross, but after further testing it would become evident that fetch queries has a limit of 2097 <condition> elements. That is 2097 per <filer> element. If a query has linked entities that has 0-2097 conditions then the main entity can have a maximum of 2095 conditions.
by Daniel Halan
23. December 2008 19:51
I've lately changed focus from MOSS 2007 to work with Microsoft Dynamics CRM solutions, anyhow. As Microsoft doesn't use the .NET 3.5 web extensions AJAX functionalities in CRM 4, and that is something that you may like to use in your ISV solutions, you need to change the "C:\Program Files\Microsoft Dynamics CRM\CRMWeb\web.config" to include all the references to the .NET 3.5 libraries. As you may know changing the web.config is not a supported customization, as after an upgrade your changes won't be there. So I have a plan of writing a small consoleapp that will add the changes to the web.config but until then here is a web.config with them included.
web.config for Microsoft CRM v4.0.7333.145 with AJAX enabled
web.config (3,35 KB)
by Daniel Halan
31. July 2007 03:38
Creating new files in a Document Library is a pretty simple task as copying the template located in the "Forms" folder. But creating a new Form is a bit harder as the template is a binary file, and what we want is a new Xml file.
The template file (with extension XSN) created by InfoPath is actually a CAB archive, that contains your form logic compiled, schemas and your xml template. So what you have to do is extract the CAB file, and copy the "template.xml" file to your Form Library. You can find a CAB extractor at The Code Project.
Here is a example of a method to get the template Xml:
private byte[] GetXmlForm(SPDocumentLibrary list) {
byte[] data = null;
SPFile file = list.ParentWeb.GetFile(list.DocumentTemplateUrl);
Extract cab = new Extract();
string szFolder = string.Concat(System.IO.Path.GetTempPath(), list.Title, "\\");
if( !Directory.Exists(szFolder) )
Directory.CreateDirectory(szFolder);
cab.ExtractStream(file.OpenBinaryStream(), szFolder);
FileStream fs = new FileStream(szFolder + "template.xml", FileMode.Open);
try {
data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
} finally {
fs.Close();
}
return data;
}
There is one more thing that has to be done before saving the template, which is to add a hyperlink to your InfoPath Template. The href should be added in the processing instruction tag "mso-infoPathSolution" ie.
<?mso-infoPathSolution href="http://server/site/library/Forms/myTemplate.xsn" ?>
Here is a snippet on how to do it:
frm.SetTemplateUrl("http://Server/Site/{0}"+list.DocumentTemplateUrl);
public void SetTemplateUrl(string url) {
foreach(XmlNode n in m_Doc.ChildNodes) {
if(n.Name == "mso-infoPathSolution") {
string szHref = string.Format("href=\"{0}\"", url);
Regex r = new Regex("href=\".*\"");
if(r.IsMatch(n.Value))
n.Value = r.Replace(n.Value, szHref);
else n.Value = string.Concat(n.Value,szHref,' ');
}
}
}
by Daniel Halan
23. March 2007 00:48
There is often that one need to get an assembly’s full name, while one can do it quite simply in C# by instancing the assembly and calling GetName(), but when setting up applications outside the development environment, You can use SN.exe to retrieve the PublicKeyToken using the -T parameter, but still it would be nice to get the whole Assembly Name, so here is a small command prompt app that does the job.
Example of an Assembly full name:
"GetAsmName, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=efc52db0448864e8"
Download the compiled application:
GetAsmName.zip (2,83 KB)
Download the source code:
GetAsmName-src.zip (2,51 KB)