Archive

Archive for the ‘Plug-Ins’ Category

Plug-ins in CRM 2011 – Useful points

Plug-in stages

  • Pre validation
    • Registered Plug-in run before the form is validated
    • Useful if you want to implement business logic before the actual validation starts.  i.e., Changes made in plug-in won’t be saved if the validation of the main system plugins complain because the changes are outside the database transaction.
    • Ex – Some “delete” plug-ins. Deletion cascades happen prior to pre-operation, therefore if you need any information about the child records, the delete plugin must be pre-validation.
  • Pre -operation
    • After validation and before the values are saved to the database
  • Post operation
    • Plugin will run after the values have been inserted/changed on the database

Database Transactions in Plug-Ins

  • Plug-ins may or may not execute within the database transaction
  • You can check if the plug-in is executing in-transaction by reading the ‘IsInTransaction‘ property of IPluginExecutionContext
  • Stages 20 and 40 are part of the database transaction while stage 10 and 50 may be part of the transaction
  • If plugin throws an exception, every action done during the transaction will be rollback

Few more Points

  • Whether a plug-in executes synchronously or asynchronously, there is a 2 minute time limit imposed on the execution of a (message) request.
  • If the execution of your plug-in logic exceeds the time limit, a Timeout exception is thrown
  • If a plug-in needs more processing time than the 2 minute time limit, consider using a workflow or other background process
  • ‘Pre-operation’ operations that CRM will do will not be carried out in pre-validation stage.
    • If you are deleting a record that has many-to-many relationship records with another entity; these relationship records will still be available in pre-validation stage, but not in pre-operation stage.
  • “Target” entity (i.e., pluginContext.InputParameters[“Target”])
    • It’s the entity on which plug-in registered
    • It only contains “dirty” attributes. if you convert to early bound, the value of the unchanged attribute will be null

Useful MSDN article :)

Adding file as “Attachment” to activities programmatically in plug-in

Hi,

We can add file as attachment and associate to the CRM objects i.e., Email, Task etc…

Email with attachment

Email with .pdf file as attachment

The entity that store attachment information is “activitymimeattachment”

Below is the code snippet to add “.pdf” file as attachment to the Email activity

Entity attachment = new Entity(“activitymimeattachment”);

attachment[“subject”] = “My Subject”;

string fileName = “Sample.pdf”;

attachment[“filename”] = fileName;

byte[] fileStream= = new byte[] { }; //Set file stream bytes

attachment[“body”] = Convert.ToBase64String(fileStream);

attachment[“mimetype”] = “text/plain”;

attachment[“attachmentnumber”] = 1;

Guid emailId; //GUID of Email activity

attachment[“objectid”] = new EntityReference(“email”, emailId);

attachment[“objecttypecode”] = “email”;

IOrganizationService service;

service.Create(attachment);

Note :-

  • In the above code the property “objecttypecode” is slight misleading, as it expects “EntityLogicalName” rather than “EntityTypeCode”
  • So make sure to set  attachment[“objecttypecode”] = EntityLogicalName (i.e., email)

🙂

Reading WCF client binding configurations from plug-in

June 16, 2012 1 comment

In one of my requirement I have to call my custom WCF service method from plug-in.

In this scenario my plug-in is WCF client and I have to read client binding configuration from plug-in.

Below are the ways you can read the binding configuration details from plug-in

  • Synchronous plug-in
    • In case of synchronous plug-in, you can place binding configuration in root <web.config> file of CRM application server
    • Open the Web.config from path “C:\Program Files\Microsoft Dynamics CRM\CRMWeb\web.config
    • Find <System.ServiceModel> node and place the client binding configuration
    • After placing the configuration, the <System.ServiceModel> looks as below
CRM root Web.config

CRM root Web.config

  • Asynchronous Plug-in
    • Since async plug-ins host on “CRM Async Service”, place the configuration details in “CrmAsyncService.exe.config” file
    • Open the “CrmAsyncService.exe.config” file from path “C:\Program Files\Microsoft Dynamics CRM\Server\bin\CrmAsyncService.exe.config
    • Add <System.ServiceModel> node and place the client binding configuration
    • After placing the configuration, the <System.ServiceModel> looks as below
CrmAsyncService.exe.config file

CrmAsyncService.exe.config file

🙂

 

“Query execution time exceeded the threshold” error in Plugins

Hi,

In one of my requirement I was accessing SSRS service API from my plugin to render and read the report

When the plugin execute the code, I was neither getting the expected result nor any error.

To troubleshoot the problem I open the event viewer and I got a warning stating below

Query execution time of 30.1 seconds exceeded the threshold of 10 seconds. Thread: 30; Database: orgname_MSCRM

Reason :- 

  • My plugin registered on Post Update of Account
  • In my plugin, I was rendering and reading a report which has dataset with “Select * From Account”
  • So the problem is with DB lock
    • On update of ‘Account’, a lock establish
    • In the Plugin code, when I try to render report it tries to execute “Select” statement on “Account” we get the above error

Fix :-

  • I modified my Select statement in report dataset with “No Lock” statement

             i.e., Select * From Account (nolock)

🙂

Sending Email using Email Template in CRM 2011

February 19, 2012 Leave a comment

Hi,

Here is the sample code to send an Email using Email template name.

Before start below are few keywords

  • Template Name   (i.e., Name of the Template)
  • Regarding Id        (i.e., GUID of the entity record which template associated with)
  • Regarding Type   (i.e., Logical name of the entity which template associated with)
  • ActivityParty[]     (i.e., Sender & Receivers Can be Users/Contacts/Accounts/Leads)
  • IOrganizationService crmService

 public void SendEmailUsingTemplate(IOrganizationService crmService,

ActivityParty[] fromParty,  ActivityParty[] toParty,

string templateName,

Guid regardingId, string regardingType)

{

try

{

// Create e-mail message.

var email = new Email

{

To = toParty,

From = fromParty,

DirectionCode = true

};

if (!string.IsNullOrEmpty(templateName))

{

Guid templateId = Guid.Empty;

// Get Template Id by Name

Entity template = GetTemplateByName(crmService, templateName);

if (template != null && template.Id != null)

{

var emailUsingTemplateReq = new SendEmailFromTemplateRequest

{

Target = email.ToEntity<Entity>(),

TemplateId = template.Id,

RegardingId = regardingId,

RegardingType = regardingType

};

var emailUsingTemplateResp = (SendEmailFromTemplateResponse)crmService.Execute(emailUsingTemplateReq);

}

else

{

// “****No email template exists with the given name ****”);

}

}

}

catch (Exception ex)

{

throw;

}

}

     private Entity GetTemplateByName(string title, IOrganizationService crmService)

{

var query = new QueryExpression();

query.EntityName = “template”;

var filter = new FilterExpression();

var condition1 = new ConditionExpression(“title”, ConditionOperator.Equal, new object[] { title });

filter.AddCondition(condition1);

query.Criteria = filter;

EntityCollection allTemplates = crmService.RetrieveMultiple(query);

Entity emailTemplate = null;

if (allTemplates.Entities.Count > 0)            {

emailTemplate = allTemplates.Entities[0];

}

return emailTemplate;

}

How Do I call this method

  • Prepare From and To Users/Contacts/Accounts
  • Pass Service,Template Name,Regarding details

// Prepare “From” activity parties

var from = new ActivityParty

{

PartyId = new EntityReference(SystemUser.EntityLogicalName, {GUID of User})

};

var fromParty = new[] { from };

// Prepare “To” activity parties

var to = new ActivityParty

{

PartyId = new EntityReference(SystemUser.EntityLogicalName, {GUID of User})

};

var toParty = new[] { to };

var orgProxy = new OrganizationServiceProxy(organizationUri, homeRealmUri, credentials, null);

IOrganizationService orgnaizationService = orgProxy;

Guid regardingntityId={GUID of record} // Ex – Guid of contact

string regardingEntityName = “contact” // Logical name ‘contact’

SendEmailUsingTemplate(orgnaizationService , fromParty, toParty, “templateName”, regardingntityId, regardingEntityName);

Hope it helps 🙂

Fetching user security roles using Linq in CRM 2011 Plug-in’s

January 17, 2012 5 comments

Hi,

Below is the sample code to fetch the User’s security roles based on the “User Id” in the Plug-in’s using Linq

        /// <summary>

/// Returns the list of User security role names

/// </summary>

private List<string> GetUserRoles(IOrganizationService service, Guid userId) {

// Create Query Expression to fetch Role Entity

var query = new QueryExpression

{

// Setting the link entity condition and filter condition criteria/

LinkEntities =

{

new LinkEntity

{

LinkFromEntityName = “role”,

LinkFromAttributeName = “roleid”,

LinkToEntityName = “systemuserroles”,

LinkToAttributeName = “roleid”,

LinkCriteria = new FilterExpression

{

FilterOperator =

LogicalOperator.And,

Conditions =

{

new ConditionExpression

{

AttributeName =  “systemuserid”,

Operator =    ConditionOperator.Equal,

Values =

{

userId

}

}

}

}

}

},

ColumnSet = new ColumnSet(true),

EntityName = “role”

};

// Obtain results from the query expression.

var userRoles = service.RetrieveMultiple(query);

// Get the usre role names collection

var roleNames = new List<string>();

if (userRoles != null)   {

roleNames.AddRange(

from entrole in userRoles.Entities

select entrole as Role

into role

where role != null && role.RoleId != null

select role.Name);

}

return roleNames;

}

How do I call this method :-

  • In your plug-in, pass the service and User Id as parameters to this method

public void Execute(IServiceProvider serviceProvider) {

context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

var service = serviceFactory.CreateOrganizationService(context.UserId);

// Get the current users Security Roles Name’s

Var roleNames = GetUserRoles(service, this.context.UserId);

}

Hope it helps 🙂

Setting default view using Plug-in’s in CRM 2011

January 17, 2012 7 comments

Hi,

We often get the requirement to set a default view based on some criteria (Ex – Could be based on logged in user role, etc…). We can achieve this using a Plug-in.

Little insight :-

  • When you click on an entity (i.e., ‘Contacts’ in my sample) in CRM application, In the background a “RetreieveMultiple” method call  happens on “savedquery” entity.

'Contacts' link

  • “savedquery” is a system entity in CRM which stores the meta data of all the views in the system

Plug-in Logic :-

  • We register a Plug-in for the RetreieveMultiple message on the savedquery entity to be executed in the post stage
  • From “Outputparameters” fetch the “BusinessEntityCollection” (i.e., Views of particular entity)
  • Loop through the views and set “isdefault” property to “true” for the desired view

–          Below is the sample code

public void Execute(IServiceProvider serviceProvider)

{

this.context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

var service = serviceFactory.CreateOrganizationService(this.context.UserId);

if (this.context.InputParameters.Contains(“Query”) && this.context.InputParameters[“Query”] is QueryExpression && this.context.Stage == 40){

var qe = (QueryExpression)this.context.InputParameters[“Query”];

if (qe.Criteria != null) {

var condition = (ConditionExpression)qe.Criteria.Conditions[1];

// “Type code” of entity you want default views ( Object type code of ‘contact’ is 2)

//  Refer Useful article on how to get “Object Type Code”

if (condition.Values[0].Equals(2)) {

// Name of the view you want to set as Default

string ourDefaultView = “My custom view – Contacts”;

if (!string.IsNullOrEmpty(ourDefaultView)){

var collection = (EntityCollection)this.context.OutputParameters[“BusinessEntityCollection”];

collection = ChangeViewCollection(ourDefaultView, collection);

this.context.OutputParameters[“BusinessEntityCollection”] = collection;

}

}

}}}

/// <summary>

/// Setting IsDefault property of views

/// </summary>

private EntityCollection ChangeViewCollection(string ourDefaultViewName, EntityCollection records){

foreach (Entity record in records.Entities){

string viewName = (string)record[“name”];

if (viewName.Equals(ourDefaultViewName)){

record[“isdefault”] = new bool();

record[“isdefault”] = true;

}

else {

record[“isdefault”] = new bool();

record[“isdefault”] = false;

}

}

return records;

}

Plug-in Registration Steps :-

Message Name – RetrieveMultiple

Entity – SavedQuery

Stage – post

  • Register the assembly & Refresh the CRM application

@@ 🙂 Here goes my 50th article. Thanks for all your visits and valuable comments 🙂 @@