I created a simple plugin that concatenates several fields and puts them together in a single result field. My plugin executes Post-Operation because some of the fields whose data it needs to retrieve and concatenate, do not get populated until another plugin (closed source / 3rd party) runs during the Post-Operation phase at a higher step rank.
Some of the fields may be blank or null and if they are null or blank, I cannot include them in the concatenation process.
Assuming no fields are blank or null, the following code works great:
namespace SetLicID.Plugins
{
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
/// <summary>
/// PostLicenseInfoCreate Plugin.
/// </summary>
public class PostLicenseInfoCreate: Plugin
{
/// <summary>
/// Initializes a new instance of the <see cref="PostLicenseInfoCreate"/> class.
/// </summary>
public PostLicenseInfoCreate()
: base(typeof(PostLicenseInfoCreate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Create", "new_s_licenseinformation", new Action<LocalPluginContext>(ExecutePostLicenseInfoCreate)));
// Note : you can register for more events here if this plugin is not specific to an individual entity and message combination.
// You may also need to update your RegisterFile.crmregister plug-in registration file to reflect any change.
}
/// <summary>
/// Executes the plug-in.
/// </summary>
/// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
/// <see cref="IPluginExecutionContext"/>,
/// <see cref="IOrganizationService"/>
/// and <see cref="ITracingService"/>
/// </param>
/// <remarks>
/// For improved performance, Microsoft Dynamics CRM caches plug-in instances.
/// The plug-in's Execute method should be written to be stateless as the constructor
/// is not called for every invocation of the plug-in. Also, multiple system threads
/// could execute the plug-in at the same time. All per invocation state information
/// is stored in the context. This means that you should not use global variables in plug-ins.
/// </remarks>
protected void ExecutePostLicenseInfoCreate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
// TODO: Implement your custom Plug-in business logic.
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity new_s_licenseinformation = (Entity)context.InputParameters["Target"];
try{
var MainLicenseID = new_s_licenseinformation["new_licenseinfoid"].ToString();
var LicenseLType = new_s_licenseinformation["new_licensenumbgtype"].ToString();
var LicenseYear = new_s_licenseinformation["new_licenseyear"].ToString();
var LicenseSPCID = new_s_licenseinformation["new_licensenumberid"].ToString();
var LicenseAutoGenNum = new_s_licenseinformation["new_licenseidcode"].ToString();
var LicenseLNType = new_s_licenseinformation["new_licensenumtype"].ToString();
var result = LicenseLType + "-" + LicenseYear + "-" + LicenseSPCID + "-" + LicenseAutoGenNum + "-" + LicenseLNType;
new_s_licenseinformation["new_licenseinfoid"] = result;
service.Update(new_s_licenseinformation);
}
catch (Exception ex) { throw new Exception("Error in Post-Operation Plug-In: " + ex.Message); }
}
}
}
}
Howevver, I need to check the value of "var LicenseSPCID = new_s_licenseinformation["new_licensenumberid"].ToString();" to see if its null or blank or if it contains data.
If it is null or blank, I need to run the following three lines of code.
var result = LicenseLType + "-" + LicenseYear + "-" + LicenseAutoGenNum + "-" + LicenseLNType; new_s_licenseinformation["new_licenseinfoid"] = result; service.Update(new_s_licenseinformation);
And if the specified field contains data, I need to run the three lines of code shown below (slightly different):
var result = LicenseLType + "-" + LicenseYear + "-" + LicenseSPCID + "-" + LicenseAutoGenNum + "-" + LicenseLNType; new_s_licenseinformation["new_licenseinfoid"] = result; service.Update(new_s_licenseinformation);
I have this working great in client side, JavaScript, mind you, but because of the Post-Operation execution requirement, I can't use it and must use a plugin.
No having much experience in C#, this type of syntax issue is a problem, until I work through it and build by syntax skill up a bit.
Never the less, this is the modified code I created to try and perform the checks but I am getting all kinds of errors. Specifically, the plugin tool debugger was showing messages that had something like "object not set to instance of an object"
namespace SetLicID.Plugins
{
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
/// <summary>
/// PostLicenseInfoCreate Plugin.
/// </summary>
public class PostLicenseInfoCreate: Plugin
{
/// <summary>
/// Initializes a new instance of the <see cref="PostLicenseInfoCreate"/> class.
/// </summary>
public PostLicenseInfoCreate()
: base(typeof(PostLicenseInfoCreate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Create", "new_s_licenseinformation", new Action<LocalPluginContext>(ExecutePostLicenseInfoCreate)));
// Note : you can register for more events here if this plugin is not specific to an individual entity and message combination.
// You may also need to update your RegisterFile.crmregister plug-in registration file to reflect any change.
}
/// <summary>
/// Executes the plug-in.
/// </summary>
/// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
/// <see cref="IPluginExecutionContext"/>,
/// <see cref="IOrganizationService"/>
/// and <see cref="ITracingService"/>
/// </param>
/// <remarks>
/// For improved performance, Microsoft Dynamics CRM caches plug-in instances.
/// The plug-in's Execute method should be written to be stateless as the constructor
/// is not called for every invocation of the plug-in. Also, multiple system threads
/// could execute the plug-in at the same time. All per invocation state information
/// is stored in the context. This means that you should not use global variables in plug-ins.
/// </remarks>
protected void ExecutePostLicenseInfoCreate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
// TODO: Implement your custom Plug-in business logic.
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity new_s_licenseinformation = (Entity)context.InputParameters["Target"];
try{
var MainLicenseID = new_s_licenseinformation["new_licenseinfoid"].ToString();
var LicenseLType = new_s_licenseinformation["new_licensenumbgtype"].ToString();
var LicenseYear = new_s_licenseinformation["new_licenseyear"].ToString();
var LicenseSPCID = new_s_licenseinformation["new_licensenumberid"].ToString();
var LicenseAutoGenNum = new_s_licenseinformation["new_licenseidcode"].ToString();
var LicenseLNType = new_s_licenseinformation["new_licensenumtype"].ToString();
if ((LicenseSPCID != null) || (LicenseSPCID != ""))
{
try
{
var result = LicenseLType + "-" + LicenseYear + "-" + LicenseSPCID + "-" + LicenseAutoGenNum + "-" + LicenseLNType;
new_s_licenseinformation["new_licenseinfoid"] = result;
service.Update(new_s_licenseinformation);
}
catch (Exception ex) { throw new Exception("Error in 1st LicenseSPCID Check: " + ex.Message); }
}
else if ((LicenseSPCID == null) || (LicenseSPCID == ""))
{
try
{
var result = LicenseLType + "-" + LicenseYear + "-" + LicenseAutoGenNum + "-" + LicenseLNType;
new_s_licenseinformation["new_licenseinfoid"] = result;
service.Update(new_s_licenseinformation);
}
catch (Exception ex) { throw new Exception("Error in 2nd LicenseSPCID Check: " + ex.Message); }
}
}
catch (Exception ex) { throw new Exception("Error in Post-Operation Plug-In: " + ex.Message); }
}
}
}
}
In the example above, using the Plugin Registration tool debugger, I was able to determine that the fault was happening either at or before the first check shown below
if ((LicenseSPCID != null) || (LicenseSPCID != ""))
That tells me that either the line of code below is not the right code to use for retrieving from a textbox that doesn't have any data in it,
var LicenseSPCID = new_s_licenseinformation["new_licensenumberid"].ToString();
OR there is something wrong with the code on a more foundational level, that only becomes a problem when I need to check if there is any text data present in one of my fields.
I also tried the code below, but got different errors, specifically related to "casting of types" and the inability to "cast a string type as an EntityReference"
namespace SetLicID.Plugins
{
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
/// <summary>
/// PostLicenseInfoCreate Plugin.
/// </summary>
public class PostLicenseInfoCreate: Plugin
{
/// <summary>
/// Initializes a new instance of the <see cref="PostLicenseInfoCreate"/> class.
/// </summary>
public PostLicenseInfoCreate()
: base(typeof(PostLicenseInfoCreate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Create", "new_s_licenseinformation", new Action<LocalPluginContext>(ExecutePostLicenseInfoCreate)));
// Note : you can register for more events here if this plugin is not specific to an individual entity and message combination.
// You may also need to update your RegisterFile.crmregister plug-in registration file to reflect any change.
}
/// <summary>
/// Executes the plug-in.
/// </summary>
/// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
/// <see cref="IPluginExecutionContext"/>,
/// <see cref="IOrganizationService"/>
/// and <see cref="ITracingService"/>
/// </param>
/// <remarks>
/// For improved performance, Microsoft Dynamics CRM caches plug-in instances.
/// The plug-in's Execute method should be written to be stateless as the constructor
/// is not called for every invocation of the plug-in. Also, multiple system threads
/// could execute the plug-in at the same time. All per invocation state information
/// is stored in the context. This means that you should not use global variables in plug-ins.
/// </remarks>
protected void ExecutePostLicenseInfoCreate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
// TODO: Implement your custom Plug-in business logic.
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity new_s_licenseinformation = (Entity)context.InputParameters["Target"];
EntityReference MainLicenseID = new_s_licenseinformation.GetAttributeValue<EntityReference>("new_licenseinfoid");
EntityReference LicenseLType = new_s_licenseinformation.GetAttributeValue<EntityReference>("new_licensenumbgtype");
EntityReference LicenseYear = new_s_licenseinformation.GetAttributeValue<EntityReference>("new_licenseyear");
EntityReference LicenseSPCID = new_s_licenseinformation.GetAttributeValue<EntityReference>("new_licensenumberid");
EntityReference LicenseAutoGenNum = new_s_licenseinformation.GetAttributeValue<EntityReference>("new_licenseidcode");
EntityReference LicenseLNType = new_s_licenseinformation.GetAttributeValue<EntityReference>("new_licensenumtype");
try{
if (LicenseSPCID != null)
{
try
{
var result = LicenseLType + "-" + LicenseYear + "-" + LicenseSPCID + "-" + LicenseAutoGenNum + "-" + LicenseLNType;
new_s_licenseinformation["new_licenseinfoid"] = result;
service.Update(new_s_licenseinformation);
}
catch (Exception ex) { throw new Exception("Error in 1st LicenseSPCID Check: " + ex.Message); }
}
else if (LicenseSPCID == null)
{
try
{
var result = LicenseLType + "-" + LicenseYear + "-" + LicenseAutoGenNum + "-" + LicenseLNType;
new_s_licenseinformation["new_licenseinfoid"] = result;
service.Update(new_s_licenseinformation);
}
catch (Exception ex) { throw new Exception("Error in 2nd LicenseSPCID Check: " + ex.Message); }
}
}
catch (Exception ex) { throw new Exception("Error in Post-Operation Plug-In: " + ex.Message); }
}
}
}
}
Given the fact that I just need to build up some basic understanding of the C# syntax is it pertains to CRM, I am hoping my assessment of this problem being one of a syntax nature is indeed the case, and someone can give me some tips or point me towards something that addresses this specific issue and others that I will be sure to encounter later on.
I looked at this, and tried to change my code to match the example here, but clearly I am doing something wrong.
Any help would be greatly appreciated.