Posted by: casperschau | March 7, 2012

CRM 2011: Working with Associate/Deassociate plugin

Hi

Yesterday I was given the task to create a plugin that could be triggered when two records (from different entities) where associated/deassociated. I didnt locate a solution that fitted my scenario in the SDK or on other blogs, so I tried  my self.

 My scenario looks like this:

Account-entity is connected to a custom entity called IT Service. The relationship is a N:N (Many to Many), which complicates the plugin a bit. On the account, if you make a new assocation to a IT Service record, my plugin will iterate through all the associations between the Account record and the IT Service records and list them in a text field on the account. This text field can then be used to show the values on a column in the account overview.

The code looks like this:

 using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Xrm.Sdk;
using System.ServiceModel;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;

namespace InsertRelatedRecordsNamespace
{
public class InsertRelatedRecordsName : IPlugin
{

public void Execute(IServiceProvider serviceProvider)
{

// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));

if (!context.InputParameters.Contains(“Relationship”)) { return; }
Relationship relationship = (Relationship)context.InputParameters["Relationship"];
if (relationship.SchemaName != “df_account_df_itservice”) { return; }

if (!context.InputParameters.Contains(“Target”)) { return; }
EntityReference target = (EntityReference)context.InputParameters["Target"];

if (!context.InputParameters.Contains(“RelatedEntities”)) { return; }
EntityReferenceCollection related = (EntityReferenceCollection)context.InputParameters["RelatedEntities"];

// Obtain the organization service reference.
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

//Extract the tracing service
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

if (tracingService == null)
throw new InvalidPluginExecutionException(“Failed to retrieve the tracing service.”);

try
{
tracingService.Trace(“Plugin has started..”);

string accItServiceField = string.Empty;

Guid accId = (Guid)target.Id;
Entity account = service.Retrieve(“account”, accId, new ColumnSet(true));

tracingService.Trace(accId.ToString());

QueryExpression query = new QueryExpression()
{
EntityName = “df_itservice”,
ColumnSet = new ColumnSet(true),
LinkEntities =
{
new LinkEntity
{
Columns = new ColumnSet(true),
LinkFromEntityName = “df_itservice”,
LinkFromAttributeName = “df_itserviceid”,
LinkToEntityName = “df_account_df_itservice”,
LinkToAttributeName = “df_itserviceid”,
LinkCriteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression
{
AttributeName = “accountid”,
Operator = ConditionOperator.Equal,
Values = { accId }
}
}
}

}
}
};
//Call Crm Service

EntityCollection interSectionValues = service.RetrieveMultiple(query);
if (interSectionValues != null && interSectionValues.Entities.Count > 0)
{
string[] itServiceContainer = new string[interSectionValues.Entities.Count];

for (int i = 0; i < interSectionValues.Entities.Count; i++)
{
tracingService.Trace(interSectionValues.Entities[i].Id.ToString());
Guid g = interSectionValues.Entities[i].Id;

Entity entityImage = service.Retrieve(“df_itservice”, g, new ColumnSet(new string[] { “df_name” }));
itServiceContainer[i] = entityImage.Attributes["df_name"].ToString();
}
foreach (string itServiceName in itServiceContainer)
{
accItServiceField += itServiceName + “, “;
}
}
account.Attributes["df_it_services"] = accItServiceField;
service.Update(account);
}
catch (FaultException ex)
{
throw new InvalidPluginExecutionException(“An error occurred in the plug-in.”, ex);
}
}
}
}

I hope it can be useful for others

Posted by: casperschau | July 14, 2010

Mail Merge on other system entities

Hi

Finally I pulled my self together to begin bloggin’ about the solution I come up with during my work with CRM 4.0.

This one came as a requirement from one of our customers, and because I couldn’t find the right solution on other blogs I had to do it myself.

I did get some help from people, especially Rhett Clinton(Blog: http://bingsoft.wordpress.com/) from MS CRM Forum. But here goes:

Issue: My client wants to get the possibility to use mail merge on the order(salesorder), opportunity and case entities. This is by default not possible. You can only use mail merge on some of the system entities and all the custom entities in the MS CRM.

I need to say that this solution is not supported so be careful.

First of all I need to enable the mail merge function on the other system enitites. This is done by going into the database and update the value for IsMailMergeEnabled in the organization database itself.

This is the sql query for that

update MetadataSchema.Entity
set ismailmergeenabled=1
where name=’salesorder’

Change the ‘salesorder’ with the opportunity and case entities to enable them too.

See more at this blog: http://nishantrana.wordpress.com/2009/10/08/enabling-mail-merge-template-for-other-system-entities/

Afterwards it should now be possible to see the mailmerge icon the Order “grid”.

Before:

After:

Now that this is in place, the client don’t just want it on the grid but also wants it to figure inside the form.

This is a bit harder, because I now need to reconfigure the ISV file in the CRM.

The way to do that is to export the ISV to you desktop and open it with an editor. In my case I use Visual Studio 2008, because its familiar for me to work in.

When you open the file you should se the XML structure for the ISV in CRM.

Locate the Salesorder section and replace it with the following code:

<Entity name=salesorder>

            <ToolBar ValidForCreate=1 ValidForUpdate=1>
                   
     <Button Icon=/_imgs/ico_mailmerge.gif JavaScript=onActionMenuClick(&apos;webmailmerge&apos;, 1088) Client=Web, Outlook AvailableOffline=true>
                              
<Titles>
                                          <
Title LCID=1033 Text=Print Order for customer />
                               </
Titles>
                              <
ToolTips>
                                           <
ToolTip LCID=1033 Text=Print Order />
                             </
ToolTips>
                   </
Button>
             </
ToolBar>
</Entity>

The XML code should look like this now:

 

Now the ISV file is reconfigured and saved, it is ready to be imported again into the CRM. (Remember to make a backup of your original ISV file.)

Voíla!!

Categories

Follow

Get every new post delivered to your Inbox.