Showing posts with label CRM 2011. Show all posts
Showing posts with label CRM 2011. Show all posts

Saturday, February 2, 2013

Fiddler, CRM and Javascript Time Saver

UPDATE: Microsoft has changed the way they send the JavaScript to the browser (See here for more info) so this tip will only work up until Rollup 11.

To get some real productivity gains when working with Javascript and CRM you can introduce Fiddler into the mix.  Fiddler has a feature called 'Auto Responder' which allows you intercept a file requested by a browser from a web server and replace it with a different file of your choice. 

By using this feature, it means that you don't have to go through the somewhat annoying process of modifying a Javascript file, deploying it and publishing it before you can test the changes; instead you can simply modify a Javascript file directly on your hard drive and then simply refresh the CRM form to test your changes.  You only need to deploy and publish the change once you are happy with the modifications and want to commit them to CRM.

Here's how to set it up:

1. Install Fiddler on your local machine
- you can download it from here for free:

2. Choose an already published web resource file from CRM (e.g. new_js_accounts)



3. Open up fiddler and click on the "Auto Responder" Tab

4. Tick the "Enable Automatic Responses", then tick "Unmatches requests passthrough" (very important!)

5. Click the add button and add a new rule, setting the first Rule box to the name of your web resource name (as highlighted on the URL in the first image above), and use the second box to "Find a file...", choosing the file which you want to replace the web resource with from your local machine.  It should look something like this:





Once this is done, you should find that whenever you refresh your CRM Form now on it should point to the local copy of the file and ignore the server one.  In Fiddler you can also turn this on/off by using the tick box next to the rule at any time.

Don't forget to still upload and publish to CRM after you are done!














Sunday, April 15, 2012

CRM 4 or CRM 2011 - Change the recipient email address

Both CRM 4 and CRM 2011 always chooses to use the primary email address (emailaddress1) when sending an email to an entity (such as Account or Contact), even though on receiving emails, CRM will map the email to the entity based on any of it's email addresses.

Every now and then I've come across a customer request where they would like to choose which of an entities email address's are used to send an email to the entity (e.g. contact).

So after a lot of experimentation, I've found a reliable way of achieving this. The key is to use a plugin on the pre-event step of the "Send" message (Send Email Message) of the email. I've found that changing the email address to be used before this is unreliable as CRM often overrides the change and re-maps it back to the primary email address.

So, to summarise my example code below:

1) I've added an "new_emailpreference" optionset to the contact entity, which lets you choose which email address is used (emailaddress1, emailaddress2 or emailaddress3).


2) I've attached the plugin as a pre-operation step of the email entity to the "Send" message.

3) The Plugin does the following:
- Grabs the email
- Loops through the "to" address (you could easily extend this to include cc and bcc as well), finding those activity parties which map to a contact.
- For each contact found, it retrieves the contact and determines if emailaddress2 or emailaddress3 has been chosen as the preferred email address to be used instead of the default.
- For that activity party, it then changes the "addressused" property to the chosen email address and updates the email record.

4) When the email gets sent via Outlook or via the Email Router, the email address that is used in the "To" address is set correctly to the email address that was chosen.






Here's the code....Note that it's for CRM 2011, however the code for CRM 4 is very similar and all the fields are the same..

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

namespace ExamplePlugin
{
public class Plugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId); // null for SYSTEM user, otherwise User Guid

ITracingService trace = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
Guid emailId = Guid.Empty;

if (context.PrimaryEntityName != "email")
{
return;
}

if (context.InputParameters.Contains("EmailId") && context.InputParameters["EmailId"] is Guid)
{
emailId = (Guid)context.InputParameters["EmailId"];

if (emailId == Guid.Empty)
{
return;
}

try
{
// Retrieve the email
var email = service.Retrieve("email", emailId, new ColumnSet(true));
if(email.Contains("to"))
{
EntityCollection activityParties = (EntityCollection)email["to"];

foreach (var activtyParty in activityParties.Entities)
{
if (activtyParty.Contains("partyid") && ((EntityReference)activtyParty["partyid"]).LogicalName == "contact")
{
// Retrieve the contact
var contact = service.Retrieve("contact",
((EntityReference)activtyParty["partyid"]).Id,
new ColumnSet(
new string[]
{ "emailaddress1",
"emailaddress2",
"emailaddress3",
"new_emailpreference" }));

if (contact.Contains("new_emailpreference") && contact["new_emailpreference"] != null)
{
if (((OptionSetValue)contact["new_emailpreference"]).Value == 100000002)
{
if (contact.Contains("emailaddress2") && ((string)contact["emailaddress2"]) != null)
{
activtyParty["addressused"] = (string)contact["emailaddress2"];
}
}
else if (((OptionSetValue)contact["new_emailpreference"]).Value == 100000003)
{
if (contact.Contains("emailaddress3") && ((string)contact["emailaddress3"]) != null)
{
activtyParty["addressused"] = (string)contact["emailaddress3"];
}
}
}
}
}

service.Update(email);
}
}
catch (Exception ex)
{
trace.Trace("Plugin Exception Encountered");
throw new InvalidPluginExecutionException(String.Format("An error occured Excuting the Plugin {0}{1}{2}", ex.Message, Environment.NewLine, ex.StackTrace));
}
finally
{
trace.Trace("Plugin Finished Executing");
}
}
else
{
return;
}


}
}
}



Saturday, July 30, 2011

CRM 2011, Silverlight and Refresh Issue

When I added a Silverlight 4.0 application to a CRM form, I discovered a problem when you referesh the page in the browser. The issue is that on refresh the Silverlight application is ready before the Xrm.Page.ui is loaded and ready to access from Silverlight.

This was a major problem for me as I needed to know what CRM Form Type was, which is done by invoking the "getFormType" method on the Xrm.Page.iu property of the form.

After trying a number of things, I found the only way to reliably access the form type was to attempt to keep accessing form type until a value was succesfully returned.

So, for those interested, here's a snipped from my silverlight application which might help you:

            // To get around problem that form may not yet be full loaded
// and so javascript can't be invoked yet, keep trying until
// we can get the form type, waiting a second between each try.
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1);
timer.Tick += (object s, EventArgs args) =>
{
int? formType = null;

// Attempt to get the Form Type
try { formType = CrmUtility.GetFormType(); }
catch { }

if (formType != null)
{
timer.Stop();

if (formType == 2) // 2 = Update
{
// ... Do work here ...
}
}
};
timer.Start();


Note that all GetFormType() method does is find the Xrm.Page.ui property and then calls .Invoke("getFormType") to get the current Form Mode from the regular Crm Javascript methods.

Also, you would expect this code to go somewhere in the initialization of your Silverlight Application.

Sunday, June 5, 2011

CRM 2011 : The given plugin assembly source type is not supported for isolated plugin assemblies.



The given plugin assembly source type is not supported for isolated plugin assemblies.


If you are getting this error message, it's because you are trying to register an assembly as sand boxed but have it's location set to disk or GAC. This is not an allowed combination, instead if you need it to be sand boxed set the storage location to the database.