Dynamics CRM Utilities for Visual Studio

I have decided to release a small utility that I developed and have been using for a long time when developing Web Resources for CRM within Visual Studio.

It allows you to publish Web Resources to CRM straight from within CRM, and if you attach it to a Keyboard Shortcut, means you can publish it with a press of a key as soon as you have finished editing it.

It allows you to edit JS, HTML, XML and images as part of a Visual Studio Solution.  It saves your connection string locally within a project, and remembers which files relate to which CRM Web Resources.  It also allows you to run FetchXML queries, and you can save your queries as part of your Project.

It can be downloaded from here, and full instructions on how to use it are also available.

CRM Utilities for Visual Studio

There are two versions, one for Visual Studio 2017 and one that is compatible with Visual Studio 2013 and 2015.

FormXML solution layering

When working with Managed Solutions, and layering them on top of each other, be mindful of one very important fact.

If you include an entity in a solution, that is also present in another solution, then the most recent solution to be installed in a system will take precedent over others when it comes to certain things such as entity forms.

For example, if you have solution A containing entity 1 and install it managed onto a server, and then later install solution B which also contains entity 1, then it’s solution B’s customisations that will be applied. If you later edit entity 1’s form within solution A and try and install it onto the server containing both solutions, the form customisations will not take.

You must always try and ensure, where possible, that each entity only exists in one solution. This would not apply if you were always going to be providing both solutions as a pair to be installed.

To safeguard, always attempt to create a new form in each solution so that customisations are carried out in each solutions specific form, and always try to avoid accidentally including entities in solutions where they don’t need to be as you can’t always roll them back due to dependancies.

Good news is that with CRM 2016, you can include only the bits you need in a solution making it easier to avoid these kind of layering issues.

Setting up Microsoft Dynamics CRM 2011 on Windows Server 2012 R2

I had a requirement to install Microsoft Dynamics 2011 onto a new server containing Microsoft Windows Server 2012 R2 for a Live Deployment, after developing using CRM on a Windows 2008 R2 server.  When the install wouldn’t work, it was then that I realised that 2011 is not officially support on Windows Server 2012.  That was an unpleasant surprise.  After doing some research, I found the required information to get it to work, and I have tried to describe the steps below for future reference.

 Step 1 – Windows Server 2012 R2

After installing the Server itself, and making sure its fully updated, you will want to make sure to add the following roles:

  • File and Storage Services
  • Web Server (IIS)
  • NET Framework 3.5 Features
  • NET Framework 4.5 Features
  • Windows Search Service
  • Windows Identify Framework

Step 2 – Retrieve the required files

As you will be unable to use your ISO or CD of Microsoft Dynamics to install, you will need to download the latest setup files from Microsoft.

Download the latest Microsoft Dynamics CRM 2011 Server setup file

Go to http://www.microsoft.com/en-us/download/details.aspx?id=27822 to download the latest Microsoft Dynamics CRM Server setup file. This also contains the appropriate SSRS Data Connector Setup File.

Download the latest Microsoft Dynamics CRM 2011 E-mail Router setup file

Go to http://www.microsoft.com/en-us/download/details.aspx?id=27818 to download the latest Microsoft Dynamics CRM E-mail Router setup file.

Download the Microsoft Dynamic CRM 2011 Self-Healing Setup (SHS)

Go to Microsoft Update Catalog http://catalog.update.microsoft.com/v7/site/Search.aspx?q=crm%20setup and then download the appropriate Setup Patches.  Instructions on what to do with these are further below.

Download the Microsoft Exchange Server MAPI Client and Collaboration Data Objects 1.2.1

Go to http://www.microsoft.com/en-ie/download/details.aspx?id=36771 and then download the appropriate Setup file.

Download the Microsoft Online Services Sign-In Assistant

Go to http://www.microsoft.com/en-gb/download/details.aspx?id=28177 and then download the appropriate Setup file.

Download the Windows Live ID Sign-in Assistant 6.5

Go to http://www.microsoft.com/en-gb/download/details.aspx?id=15106 and then download the appropriate Setup file.

Download the Update Rollup 17 for Microsoft Dynamics CRM 2011

Go to http://www.microsoft.com/en-us/download/details.aspx?id=42672 to download Update Rollup 17 (or if there is a later version, then download that).

Step 3 – Configure your CRM Setup

  • Extract your main CRM setup files to a folder on your server’s hard disk, but don’t run it yet. For example, extract it to d:\setup
  • Run and extract the Self-Healing Setup file for the Server setup. Within the resulting folder you will see lots of similar files :
  • Find the file for your language (English is 1033, so the file you need is en-server_kb2434455_amd64_1033_xxxxxxxxxxxxx.cab) and double click the file. Copy the file contained (extension msp) into the same folder that your CRM setup files are (so d:\setup). You could also remove all the extra characters from the end of the file if you wish.
  • Create a custom setup file called config.xml and place it in the same setup folder. The contents of the file are below :
    <Patch update="true">d:\setup\Server_KB2434455_amd64_1033.msp</Patch>


Step 4 – Run the setup

You can now run the setup from a command line by doing typing the following into a command prompt:

SetupServer.exe /config d:\setup\config.xml

This should then start the normal CRM installation routine. The checking for update step should show “Setup has finished downloading the update” to confirm that the setup has picked the SHS up correctly from the config file. After this, you can install CRM as normal.

Once it has fully installed, you must then run the appropriate latest update rollup to make sure your CRM instance is fully patched and compatible.

 Step 5 – Setup SSRS Data Connector for CRM 2011

I found that installing the SSRS was less problematic. I was installing to a separate Reporting Services Server, and I had setup an appropriate config file to incorporate the relevant SHS file into the setup procedure, but I couldn’t get the main setup to run.  It turned out that I was able to just install the SSRS Data Connector without any issue by default.

After its installed, make sure you run the Update Rollup 17.

 Step 6 – Setup the Email Router for Dynamics CRM 2011


The setup for the email router also did not require the SHS hack, but, there were other pre-requisites that I had to install before I could proceed. Once I found out what I had to install (the automatic download and install of the setup would not work) everything went smoothly.  Just install the following three components onto the server, and the Router setup should then work without any issue.

  • First, Install the Microsoft Exchange Server MAPI Client and Collaboration Data Objects 1.2.1.
  • Then install the Microsoft Online Services Sign-In Assistant
  • And finally, install the Windows Live ID Sign-in Assistant 6.5

With these three components installed, the router installation was a breeze.


Fixing a WCF Web Service for Cross Domain/Browser Support

I had an issue recently where I was attempting to make my CRM 2011 customisations cross browser compatible. The issue was when I was calling a Web Service via Jquery’s AJAX methods. It was working fine in Internet Explorer, but when I was trying to access it from a Web Resource within Chrome, I was getting an issue that was suggesting it was a cross domain problem.

Although the web service was running on the same host, as it was on a different port, it was being classed as a cross domain ajax call and Chrome was stopping it.

I spent a while trying to find out how to fix the client JavaScript assuming the issue was how I was calling it, and then I stumbled on some useful information about Web Services and a nice little piece of code to enable the web service to work perfectly, leaving the client alone.

The issue boiled down to some extra calls being made to gather OPTIONS around the safety of the request.

“OPTIONS” Request called as “Preflight Request” – “preflighted” requests first send an HTTP OPTIONS request header to the resource on the other domain, in order to determine whether the actual request is safe to send and this request expects appropriate headers saying that service is allowing to access the service as a Response

The fix is to add a global.asax file to the web service project and include the following code which handles this OPTIONS request. Build, and deploy and all of a sudden it was working fine in Chrome as well 🙂

protected void Application_BeginRequest(object sender, EventArgs e)
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");

Popup a new entity form with default values via JavaScript

One of the most useful features I have found recently was being able to use the Xrm object to create window popups for new entities.  I was still using the old way of creating a URL with all the correct parameters, but I didn’t realise that the Xrm.Utilities object now has some very handy functions to allow you to do this.  You can even set up some default properties so that some of the fields are already populated.

function CreateIncident() {
//get Account GUID and Name
var AccountGUID = Xrm.Page.data.entity.getId();
var AccountName = Xrm.Page.data.entity.attributes.get("name").getValue();
//define default values for new Incident record
var parameters = {};
parameters["title"] = "New customer support request";
parameters["casetypecode"] = "3";
parameters["customerid"] = AccountGUID;
parameters["customeridname"] = AccountName;
parameters["customeridtype"] = "account";
//pop incident form with default values
Xrm.Utility.openEntityForm("incident", null, parameters);

Customising the Activity Views (and other such views) via Plugins

RetrieveMultiplePluginfeatureThe Requirement

I had a requirement to display a list of activities, both open and closed on the dashboard. Simple enough I hear you say. Well, it was until I needed to include a few more fields to make the user experience better. I wanted to categorise the activities, so as well as showing the type of activity (email,phone,letter,task), I wanted to give them a short description that would make a lengthy list of activities easily readable.

The Idea

Upon looking at the activities, such as email and phone call, I noticed they had a system default field called category, of which it was a single line of text. As it was present on all of the activities, I thought I would just use it. After much time spent updating my workflows to populate these category fields with the appropriate tags, I was ready to update the view.

The Problem

Bugger, it was then that I realised that the category field was unique to each activity, and not stored on the activity pointer (the entity that you would normally use to list all types of activities in one view). The activity pointer had the subject and description fields that are shared across other activities (plus a few more), but not the category field. And to top it off, the activity pointer entity is not customisable. So, at that point I started to think about using workflows or JavaScript to just simply prepend the tags I wanted to use to the beginning of the subject line, but it soon became apparent that it was not going to be suitable as there would be too much involved with making sure manual updates to activities didn’t spoil my tagging.

I began the “google”.

The Solution

Eventually, I happened upon a possible solution using plugins. Initially I was thinking of using a create or update plugin to change the subject field. Got too confusing, but, there was light at the end of the tunnel. I began experimenting with a plugin for the RetrieveMultiple command. This is what provides data for views within Dynamics, and even the activity pointer entity can have a RetrieveMultiple plugin to intercept the data it is about to send back to the web browser allowing you to tinker with the data returned.

To begin with, using the CRM Developer Toolkit for Visual Studio 2012, I browsed to the Activity Entity in the CRM Explorer window, right clicked and selected Create Plugin. Below are the selections I made to set up the plugin.


After that, I just added the code (at the bottom of this post) to intercept the returned EntityCollection’s subject field, and alter it in such a way so that it has the activities category and direction fields within.

The below line gets the EntityCollection that is about to be returned to the clients Grid View from the plugins OutputParameters collection.

EntityCollection entityCollection = (EntityCollection)localContext.PluginExecutionContext.OutputParameters["BusinessEntityCollection"];

I then loop through every entity, find the category from the appropriate activity entity (the activitypointer id is the same id that is stored within the email entity for example), and then modify the activitypointer’s subject attribute to include the category.

It really is that simple.

Interesting, this could be used in all kind of situations where you need to alter the displayed views (perhaps hiding fields based on security roles, or encrypting/decrypting passwords for viewing etc). One of the key uses though may be to retrieve data from other entities to include in a view that may not be possible by just using fetchxml.

Below is the Execute code to include in the plugin to achieve what I have described.

protected void ExecutePostActivityRetrieveMultiple(LocalPluginContext localContext)
if (localContext == null)
throw new ArgumentNullException("localContext");
if (localContext.PluginExecutionContext.OutputParameters.Contains("BusinessEntityCollection"))
EntityCollection entityCollection =
if (true) // This could be some form of user role check
if (entityCollection.Entities.Count > 0)
Entity ActivityEntity = null;
foreach (Entity entity in entityCollection.Entities)
if (entity.Contains("activitytypecode"))
string type = entity.Attributes["activitytypecode"].ToString();
if (type != "")
// These Activities have a direction field to indicate outgoing or incoming
if (type == "email" || type == "letter" || type == "phonecall")

ActivityEntity = localContext.OrganizationService.Retrieve(
type, entity.Id, new ColumnSet("category", "directioncode"));
ActivityEntity = localContext.OrganizationService.Retrieve(
type, entity.Id, new ColumnSet("category"));
if (ActivityEntity.Attributes.Contains("category"))
if (ActivityEntity.Attributes.Contains("directioncode"))
entity.Attributes["subject"] =
ActivityEntity.Attributes["category"].ToString().PadRight(30) + " – " +
((bool)ActivityEntity.Attributes["directioncode"] ? "Outgoing" : "Incoming")
+ " – " + entity.Attributes["subject"];
entity.Attributes["subject"] =
ActivityEntity.Attributes["category"].ToString().PadRight(30) + " – " +

Object Type Codes Cheat Sheet for Dynamics CRM 2011

Sometimes when developing, you need the entity object type code (of which there are quite a few).  Below is a quick list of them for reference.


1 Account
2 Contact
3 Opportunity
4 Lead
5 Annotation
6 BusinessUnitMap
7 Owner
8 SystemUser
9 Team
10 BusinessUnit
11 PrincipalObjectAccess
12 RolePrivileges
13 SystemUserLicenses
14 SystemUserPrincipals
15 SystemUserRoles
16 AccountLeads
17 ContactInvoices
18 ContactQuotes
19 ContactOrders
20 ServiceContractContacts
21 ProductSalesLiterature
22 ContactLeads
23 TeamMembership
24 LeadCompetitors
25 OpportunityCompetitors
26 CompetitorSalesLiterature
27 LeadProduct
28 RoleTemplatePrivileges
29 Subscription
30 FilterTemplate
31 PrivilegeObjectTypeCodes
32 SalesProcessInstance
33 SubscriptionSyncInfo
35 SubscriptionTrackingDeletedObject
36 ClientUpdate
37 SubscriptionManuallyTrackedObject
40 TeamRoles
41 PrincipalEntityMap
42 SystemUserBusinessUnitEntityMap
43 PrincipalAttributeAccessMap
44 PrincipalObjectAttributeAccess
112 Incident
123 Competitor
126 DocumentIndex
127 KbArticle
129 Subject
132 BusinessUnitNewsArticle
135 ActivityParty
150 UserSettings
1001 ActivityAttachment
1002 Attachment
1003 InternalAddress
1004 CompetitorAddress
1006 CompetitorProduct
1010 Contract
1011 ContractDetail
1013 Discount
1016 KbArticleTemplate
1017 LeadAddress
1019 Organization
1021 OrganizationUI
1022 PriceLevel
1023 Privilege
1024 Product
1025 ProductAssociation
1026 ProductPriceLevel
1028 ProductSubstitute
1030 SystemForm
1031 UserForm
1036 Role
1037 RoleTemplate
1038 SalesLiterature
1039 SavedQuery
1043 StringMap
1055 UoM
1056 UoMSchedule
1070 SalesLiteratureItem
1071 CustomerAddress
1072 SubscriptionClients
1075 StatusMap
1080 DiscountType
1082 KbArticleComment
1083 OpportunityProduct
1084 Quote
1085 QuoteDetail
1086 UserFiscalCalendar
1088 SalesOrder
1089 SalesOrderDetail
1090 Invoice
1091 InvoiceDetail
1111 SavedQueryVisualization
1112 UserQueryVisualization
1113 RibbonTabToCommandMap
1115 RibbonContextGroup
1116 RibbonCommand
1117 RibbonRule
1120 RibbonCustomization
1130 RibbonDiff
1140 ReplicationBacklog
1200 FieldSecurityProfile
1201 FieldPermission
1202 SystemUserProfiles
1203 TeamProfiles
2000 UserFiscalCalendar
2001 UserFiscalCalendar
2002 UserFiscalCalendar
2003 UserFiscalCalendar
2004 UserFiscalCalendar
2010 Template
2011 ContractTemplate
2012 UnresolvedAddress
2013 Territory
2020 Queue
2027 License
2029 QueueItem
2500 UserEntityUISettings
2501 UserEntityInstanceData
3000 IntegrationStatus
3231 ConnectionRole
3232 ConnectionRoleAssociation
3233 ConnectionRoleObjectTypeCode
3234 Connection
4000 Equipment
4001 Service
4002 Resource
4003 Calendar
4004 CalendarRule
4005 ResourceGroup
4006 ResourceSpec
4007 ConstraintBasedGroup
4009 Site
4010 ResourceGroupExpansion
4011 InterProcessLock
4023 EmailHash
4101 DisplayStringMap
4102 DisplayString
4110 Notification
4200 ActivityPointer
4201 Appointment
4202 Email
4204 Fax
4206 IncidentResolution
4207 Letter
4208 OpportunityClose
4209 OrderClose
4210 PhoneCall
4211 QuoteClose
4212 Task
4214 ServiceAppointment
4215 Commitment
4230 UserQuery
4250 RecurrenceRule
4251 RecurringAppointmentMaster
4299 EmailSearch
4300 List
4301 ListMember
4400 Campaign
4401 CampaignResponse
4402 CampaignActivity
4403 CampaignItem
4404 CampaignActivityItem
4405 BulkOperationLog
4406 BulkOperation
4410 Import
4411 ImportMap
4412 ImportFile
4413 ImportData
4414 DuplicateRule
4415 DuplicateRecord
4416 DuplicateRuleCondition
4417 ColumnMapping
4418 PickListMapping
4419 LookUpMapping
4420 OwnerMapping
4423 ImportLog
4424 BulkDeleteOperation
4425 BulkDeleteFailure
4426 TransformationMapping
4427 TransformationParameterMapping
4428 ImportEntityMapping
4500 RelationshipRole
4501 RelationshipRoleMap
4502 CustomerRelationship
4503 CustomerOpportunityRole
4567 Audit
4600 EntityMap
4601 AttributeMap
4602 PluginType
4603 PluginTypeStatistic
4605 PluginAssembly
4606 SdkMessage
4607 SdkMessageFilter
4608 SdkMessageProcessingStep
4609 SdkMessageRequest
4610 SdkMessageResponse
4611 SdkMessageResponseField
4613 SdkMessagePair
4614 SdkMessageRequestField
4615 SdkMessageProcessingStepImage
4616 SdkMessageProcessingStepSecureConfig
4618 ServiceEndpoint
4700 AsyncOperation
4702 WorkflowWaitSubscription
4703 Workflow
4704 WorkflowDependency
4705 IsvConfig
4706 WorkflowLog
4707 ApplicationFile
4708 OrganizationStatistic
4709 SiteMap
4710 ProcessSession
4800 WebWizard
4802 WizardPage
4803 WizardAccessPrivilege
4810 TimeZoneDefinition
4811 TimeZoneRule
4812 TimeZoneLocalizedName
7100 Solution
7101 Publisher
7102 PublisherAddress
7103 SolutionComponent
7105 Dependency
7106 DependencyNode
7107 InvalidDependency
8000 Post
8001 PostRole
8002 PostRegarding
8003 PostFollow
8005 PostComment
8006 PostLike
9100 Report
9101 ReportEntity
9102 ReportCategory
9103 ReportVisibility
9104 ReportLink
9105 TransactionCurrency
9106 MailMergeTemplate
9107 ImportJob
9333 WebResource
9502 SharePointSite
9508 SharePointDocumentLocation
9600 Goal
9602 GoalRollupQuery
9603 Metric
9604 RollupField
10021 msdyn_PostAlbum
10022 msdyn_PostConfig
10023 msdyn_PostRuleConfig

LinqPad for testing plugin development and workflow activities

We all know that developing and debugging plugins with Microsoft Dynamics CRM 2011 (and 2013) can be troublesome.  Having to code blind and expecting it to work when you deploy it to your server to test it.

I have recently started using LinqPad to develop my plugin and workflow code, testing to make sure the logic works, before copying the code into Visual Studio and deploying.

LinqPad is a very handy tool that reminds me of days before where you could just write code straight into an editor, and run it, not having to create projects, and building and debugging.

Its fully extendable, and once you have it set up, makes writing straight forward C# code and Linq queries very easy.  There are a couple of ways to use it depending on if you prefer early or late bound approaches to manipulating and retrieving your Dynamics Entities.

First things first though, download and install it from the LinqPad website.


Install it on your machine, and run it.

There are two ways of using it, late bind and early bind.  I prefer Late bind (where you reference your entities in a generic fashion) but early bind (where you can reference your entities and attributes by name) has its uses.  For plugin development, late bind is bar far the easiest to get started with as you dont have to generate class files for your Dynamics deployment, and your assemblies are much smaller.

To set up early bind, you simply add the Dynamics URL as a data connection within LinqPad, and your ready to go.  To use late bind, you have to write some C# code to enable a connection to your Dynamics Server (but don’t worry, I am going to provide you with some sample code).

Adding a connection for Early Bind

To add a connection so that you can reference your entities via name, simply click on the Add Connection link at the top left to bring up the “Choose Data Context” window.


Choose WCF Data Services 5.5 (Odata 3) and on the next screen, enter the following URI :



You can leave the username and password section blank if your logged in with Active Directory, ad you can also select either XML or JSON. When you hit OK, the data connection will now appear and you can expand it out to show all of your entities, and their attributes.


You can now begin writing code as long as the code window has the connection set to use the connection you have just created.

Adding a connection using custom code

In my opinion, the best way to use LinqPad is to write your own connection. If you are a registered user of LinqPad, you can use NuGet to download all of the CRM assemblies ready to roll, but I am going to go through the steps required in case you are just using the free version.

The first thing you need to do is to select the My Extensions document in the bottom left window. This is where you can write some code that will allow you to connect to Microsoft Dynamics.  I have enclosed a sample below which you should just be able to copy and paste into the window once you have set up the environment.

First things first, in the My Extensions window, hit the F4 key to bring up the windows properties. In this window, this is where you need to add all of the MSCRM SDK DLL’s you will be requiring, such as


Simply browse to the files (assuming you have already download the SDK) and add them in to your extensions window. You then also need to set up your namespaces so that you can access them.


Now for the code that you will use to connect to Dynamics. Simply Paste the following :

void Main()
	// Write code to test your extensions here. Press F5 to compile and run.

/// My Extensions is a class to allow a connection to MS Dynamics 2011	
public static class MyExtensions
	// Stores a number of specific connection strings
	public static  NameValueCollection ServerConnections = new NameValueCollection();
	// Populates the connection strings
	public static void PopulateConnectionStrings()
	// GetOrgContext - return a connection 
	public static OrganizationServiceContext GetOrgContext(string connectionString)
			CrmConnection connection = CrmConnection.Parse(ServerConnections[connectionString]);
			var result = new Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy(
			Microsoft.Xrm.Sdk.Client.OrganizationServiceContext orgcontext = new OrganizationServiceContext(result);
			return orgcontext;
	// GetOrgService - return a connection
	public static IOrganizationService GetOrgService(string connectionString)
			CrmConnection connection = CrmConnection.Parse(ServerConnections[connectionString]);
			var result = new Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy(
			return result;

Hit the green play button, and in theory, it should build and compile.

I have coded this so that you can add extra connection strings in case you have multiple environments. You can then simply instantiate a connection by using :

var conn = MyExtensions.GetOrgContext("HALL2011");

Writing Code

Now, to begin, create a new query by clicking on the plus sign at the top of the main text window. A query will be set up and it should be ready to go with all of the assemblies and namespaces you set up within your extension.  Make sure you have C# Statements selected, and type in the following as a simple test to make sure everything is working :

var conn = MyExtensions.GetOrgContext("HALL2011");

var response = (WhoAmIResponse)conn.Execute(new WhoAmIRequest());


Should give you the following


The results, by default are rendered as XML, but you can click the grid button just along from the run button to display the data as a grid. You will notice the line response.Dump().  LinqPad extends everything with this command, and will output it within the results pane.  You can use this to output variables and objects so you can see what it looks like.


And your set. You can now right code, linq queries etc and run them straight away.  If you change the Language selector to C# Program, you can even create functions and test them just as you would in Visual Studio.  This allows you to test all of your plugin and workflow activities logic within LinqPad before putting the code into your CRM server. You can easily add other reference assemblies and namespaces to your queries as you see fit.

Another example (using an email template and then finding the attachments)

InstantiateTemplateRequest instTemplateReq = new InstantiateTemplateRequest


TemplateId = new Guid("CE6E9346-8FFB-E311-8997-005056A507B0"),

ObjectId = new Guid("995623E6-58F8-E311-8997-005056A507B0"),

ObjectType = "incident"


InstantiateTemplateResponse instTemplateResp = (InstantiateTemplateResponse)conn.Execute(instTemplateReq);

Guid id = new Guid("CE6E9346-8FFB-E311-8997-005056A507B0");

var files = from f in conn.CreateQuery("activitymimeattachment")

where (Guid)f["objectid"] == id &&

(string)f["objecttypecode"] == "template"

selectnew {f};


Debugging within Visual Studio

And it gets better, why not just use LinqPad to set up some test data, and then call your plugin code directly and debug within Visual Studio.

In LinkPad, within your query window, hit the F4 key and add your plugin assembly and its namespace to your query properties.

In LinqPad, you can set up any variables your plugin code may need. As an example, I have started to place my plugin logic within a separate static class with various methods that take parameters.  This way, the plugin can deal with the input and output parameters, but I then have separate code blocks that do the processing.  In LinqPad, you can then simply call this logic with the appropriate parameters.

If you then use the command


It will kick off Visual Studio’s debugger and you can step through your plugin code. Simples.

Child Workflows in Dynamics CRM 2011

While facing a particular issue in how to design some workflows that I just knew where going to change in structure down the line, I found this very useful article which I would recomend having a look at.

When and How to use Child Workflows

I have been using them to add all of my procedural code, such as getting queue’s, creating emails etc and all the related setup.  This would be the child workflow.

Then all my condition statements and decision making appears in the main workflow which simply calls the child workflow at the correct time.  This means if your main workflows structure changes, you do not have to redo all of the other steps (as we all know how poor the Dynamics Workflow Designer is at changing structure, moving things and cut,copy,paste).

This is the way I will be handling things from now on.

Updating Plugins and Workflow Activities

When updating plugins or workflow activities, if you are adding input / output parameters, or changing the name or display, sometimes after updating, the changes do not take effect within the Dynamics Workflow editor.

Instead of having to stop and start services, did you know that the update can be triggered by changing the assembly version information before you update.

In Visual Studio, just edit the properties of your Workflow Project as outlined in the screenshots, increment the assembly version, and rebuild and deploy.  The change in version will be enough for Dynamics to refresh its cache for using the activity in the workflow designer.