Jul 27, 2014

Using same plug-in for all Create, Update and Delete events

In some cases, we may need to execute same plug-in for Create, Update and Delete. Is this possible?

Yep, you don’t need to write many plug-ins if it’s the same logic. Only thing, we need to have two different ways of triggering the logic in same code. If you need to refresh the knowledge, check Create, Update and Delete code snippets.

You can write a one code accommodating both needs. Different is, in Create/Update we get the target entity in the context while in Delete we get only the reference.

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

  // Create, Update
  
  if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
  {
     TargetEnt = (Entity)context.InputParameters["Target"];

     //Logic here
     //Read Guid like this; 
     //Guid _officeid = (Guid)TargetEnt.Attributes["new_officeid"];

  }

  // Delete

  if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)
  {
     EntityReference EntityRef = (EntityReference)context.InputParameters["Target"];

     //Logic here
     //Read Entity reference like this; 
     //EntityReference _officeidRef = (EntityReference)context.InputParameters["Target"];

  }
  
}
(*I suppose we use a custom entity called new_office in this example)

Hope this is Clear…  register this all Create, Update and Delete steps.

Note:
In Create/Update section always get field values by retrieve method (passing Guid), rather than reading via target entity. If you can remember, though we get all fields in the context for Create, we get only updated fields in Update. Remember?

Jul 14, 2014

Sample custom workflow

We will see how you do a custom workflow. We all know how to do things with a normal workflow. Still in some instances, built in wizard of workflows are not able to cater our need. In that case we need to do a code to be executed as a part of the workflow.  

Pl check below code. This shows you a skeleton of a workflow code. If you notice, what we really do is reading some attributes from the context and do whatever we need to do. In fact, idea is quite similar to construction of a plug-ins.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Activities;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;

namespace CustomWFtest
{
 public class SetAccountOffice : CodeActivity
 {
  protected override void Execute(CodeActivityContext executionContext)
  {
    IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();

    if (context == null)
    {
        throw new InvalidPluginExecutionException("Failed to retrieve workflow context.");
    }

    IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
    IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    OrgOrionDatamodel orgSvcContext = new OrgOrionDatamodel(service);

    try
    {
        throw new Exception("testing exception .. primary ID is : " + context.PrimaryEntityId);
       
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        context = null;
    }
  }
 }
}

Context gives you some attributes from the triggering point of the workflow. Our sample just throw an exception with primary Id. Use the intellisense to check what other attributes we got in the context and decide how you go with it.


Check below illustration to know what other references we use in this class library project (same as plug-in). Microsoft.Xrm.sdk.workflow dll is the new one we need to add. As same as plug-in development, you must sign the assembly (right click the project > properties > Signing > create .snk file).


Once you do the code, build the dll and register through the plug-in registration tool.


Then you can start workflow wizard to do the needful.  Now, within the wizard, you can see our newly registered DLL with custom workflow name as under “Add Step”. Now you can easily add it as a step.


You can see, in our sample, the exception with primary ID of the record. (go to system jobs and check)

If you wisely study you may realize context we used within the code contains the data relevant to this triggering entity and etc. Hope you understand “context” is the link in between the workflow and your code. Once you understand this, sky is the limit for actions you can do within the code.

Jul 3, 2014

Test Plug-in execution using trace

One of the pervious posts,  we discussed few ways of testing how plug-in is executing and whether expected values are being retrieved to the right variables and etc.

Anyway, recently I found tracing as one of the other effective way of testing a plug-in.
What is done here is usage of tracer object (use Microsoft.Xrm.Sdk) to trace any value within the flow.

Below code will give an idea how it’s being done in your code. Please have a good look at the throw of exception line within the catch block. See how the traced information has been passed with the exception.

using System;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System.ServiceModel;

namespace ABCandComSol
{
public class AccountQualifier : IPlugin 
{
  public void Execute(IServiceProvider serviceProvider)
  {

    ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

    try
    {
        //Any information you need to trace
        // ex;
        //tracer.Trace("Account:{0} and Guid:{1}", _account.Name, _account.accountid);
    }
    catch (Exception ex)
    {
        tracer.Trace(ex.Message);
        throw new InvalidPluginExecutionException("[" + ex.Message + "]" + ex.StackTrace, ex);
    }
    finally
    {
    }

  }
}
}

Once plug-in is failed all the details you put in the tracer is viewable.  So positive side is, you don’t need to remove any code once code starts working fine. In future, if client say something failed, you got all the information you need in hand!

How to see the trace values

Synchronous Plug-in: Once exception is thrown, check information, you may see all the tracer information within error information.

Asynchronous Plug-in: If plug-in fails, a system jobs will show relevant failed entry. Once you open it, you may see all the tracer information. Further reading here.

Note
In fact, if you want to test something for a working code, you may need to forcefully throw an exception.