CRM 2011: OData/REST Query Expand Filter
You already probably knew about Expand functionality in CRM 2011 OData/REST Query. It is a useful functionality to include fields from a single related entity.
But here is a quick preview:
http://.../ContactSet?$select=FullName,contact_originating_lead/Subject&$expand=contact_originating_lead
In the example above, I want to retrieve full name of contacts and also the subject of their originating leads.
I can further do a query on the lead subject equals ‘ab’
http://.../ContactSet?$select=FullName,contact_originating_lead/Subject&$expand=contact_originating_lead&$filter=contact_originating_lead/Subject eq 'ab'
Just as easy as 1, 2, 3.
Some caveats though:
1. You can expand on multiple relationships but beware of query performance.
http://.../ContactSet?$select=FullName,contact_originating_lead/Subject,account_primary_contact/Name,contactleads_association/Address1_PostOfficeBox&$expand=contact_originating_lead,account_primary_contact,contactleads_association&$filter=FirstName eq 'ab'
In saying that I was never able to get expanding One-To-Many relationship working, and I find expanding the Many-To-Many relationship hard to work with, so the only one that works well for me was the Many-To-One. Kinda make sense to me due to the join.
2. Filtering on multiple entity types is unsupported. This means if you are adding filter, you can only filter on a single entity type.
http://.../ContactSet?$select=FullName,contact_originating_lead/Subject&$expand=contact_originating_lead&$filter=FirstName eq 'ab' and contact_originating_lead/Subject eq 'ab'
The above is unsupported because it is filtering on contact entity and also contact_orginating_lead relationship entity.
3. Although you can expand to all types of relationships, filtering with expand works only for many-to-one relationship with the entity on query.
Cheers – Sy
CRM 2011: StateCode and StatusCode Case Incosistency
Here is a little caveat to CRM 2011 customization as discovered by Iain after causing him much discomfort.
System (Built-In, Out-Of-The-Box, etc) Entities have StateCode and StatusCode.
Custom Entities have statecode and statuscode.
Note the different case between them.
Sy
CRM 2011: Filtering Attributes (Plugin) and Early Bound Code
Setting Filtering Attributes on Plugin Step is one of the things that is often overlooked. That is a shame because using Filtering Attributes can improve plugin performance significantly; and not to mention simplify execution order if you have complex chains of plugins.
According to MSDN article here, Filtering Attributes is
A list of entity attributes that, when changed, cause the plug-in to execute. A value of null causes the plug-in to execute if any of the attributes change.
Early Bound Code
I am very much in the favor of using early bound code as it provides compile-time checking, linq, and other perks. However, what we found out is that updating retrieved record using early bound code organisation context will bypass filtering attributes as it submits the record’s entire object graph back to CRM. CRM therefore assumes that all the attributes are being updated and thus effectively rendering filtering attributes useless.
Cheers – Sy
CRM 2011: Upload Attachment/File in Annotation/Note Programmatically
In this post, I’ll provide a quick code snippet to upload attachment/file via CRM 2011 annotation/note.
Inh this example I am using early-bound code generated by crmsvcutil.
var serviceContext = new GeneratedServiceContext();
//We need to create the annotation record first
var annotation = new Annotation();
annotation.Subject = "Attachment Test";
annotation.ObjectId = new EntityReference("account", accountId);
annotation.ObjectTypeCode = "account";
serviceContext.AddObject(annotation);
//Now we get the base64 representation of the file
var textContent = "Hello World!";
byte[] bytes = new byte[textContent.Length * sizeof(char)];
Buffer.BlockCopy(textContent.ToCharArray(), 0, bytes, 0, bytes.Length);
var textContentBase64 = Convert.ToBase64String(bytes);
annotation.FileName = "Plain text file";
annotation.MimeType = @"text/plain";
annotation.DocumentBody = textContentBase64;
serviceContext.UpdateObject(annotation);
serviceContext.SaveChanges();
Cheers – Sy
app.config Transform for non-Web Project (web.config style)
web.config style Transform is very useful. Unfortunately, it’s only available for web project. Here’s how to make it available for non-web project.
1. Unload your project
2. Edit your project file
3. Edit your config entries – note the DependentUpon tag
<ItemGroup>
<Content Include="app.config" />
<Content Include="app.Debug.config">
<DependentUpon>app.config</DependentUpon>
</Content>
<Content Include="app.Test.config">
<DependentUpon>app.config</DependentUpon>
</Content>
<Content Include="app.Release.config">
<DependentUpon>app.config</DependentUpon>
</Content>
</ItemGroup>
4. Add transform task at the bottom of file
<Project>
...
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="exists('app.$(Configuration).config')">
<!-- Generate transformed app config in the intermediate directory -->
<TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
<!-- Force build process to use the transformed configuration file from now on. -->
<ItemGroup>
<AppConfigWithTargetPath Remove="app.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
5. Reload your project
Cheers, Sy
CRM 2011: Add/Remove Target Marketing List to Campaign Request/Message
On a recent project, we need to provide counts for the number of ‘targets’ for campaign. The theory in principle is simple, using plugin get all the target marketing list of a campaign and count the number of their members. For simplicity sake, only ‘static’ list is part of it. But of course the plugin must attach to an event.
First thought that comes to mind was Associate message. And it’s wrong!!!
Turns out, if you want to add another campaign, list, product or salesliterature to a campaign, you have to use AddItemCampaignRequest. And the corresponding message for plugin is, you guessed it AddItem.
For removing, RemoveItemCampaignRequest and the corresponding message for plugin is RemoveItem
Further read about the request classes:
- AddItemCampaignRequest
- RemoveItemCampaignRequest
Cheers,
Sy
CRM 2011: CRM Explorer missing from Visual Studio 2010 (Tools)
Check these prerequisites to have CRM 2011 Developer Toolkit functioning properly:
1. Visual Studio 2010 Professional or later
2. Microsoft Silverlight 4
3. Windows Identity Foundation
Or you may be missing this section in your solution file.
Global
GlobalSection(CRMSolutionProperties) = preSolution
SolutionIsBoundToCRM = TRUE
EndGlobalSection
EndGlobal
Courtesy of Chris Moreton.
Cheers – Sy