I need to write plugin in CRM 2013 that do two thing:
If statecode = 3 and the field el_meeting_in_outlook_id is empty I
need to create a new appoitment.
If statecode = 3 and the field el_meeting_in_outlook_id is not empty
I need to update an existing appoitment.
This is what I wrote:
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using tmura_Entity_Plugins;
namespace tmura_Entity__Plugins
{
public class postCreateUpdateServiceAppointment : Plugin
{
public postCreateUpdateServiceAppointment()
: base(typeof(postCreateUpdateServiceAppointment))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Create", null, new Action<LocalPluginContext>(ExecutePostCreate)));
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Update", null, new Action<LocalPluginContext>(ExecutePostUpdate)));
}
private void ExecutePostCreate(LocalPluginContext obj)
{
Logger.WriteMessage("Enter ExecutePostCreate", CrmLogService.MessageLevel.Info, "");
if ((obj.PluginExecutionContext.InputParameters.Contains("Target")) && (obj.PluginExecutionContext.InputParameters["Target"] is Entity))
{
Entity serviceAppontment = (Entity)obj.PluginExecutionContext.InputParameters["Target"];
if (serviceAppontment.LogicalName != "serviceappointment")
return;
Logger.WriteMessage("", CrmLogService.MessageLevel.Info, "");
if ((serviceAppontment.Attributes.Contains("statecode")) || ((int)(serviceAppontment.Attributes["statecode"]) == 3) && (serviceAppontment.Attributes["el_meeting_in_outlook_id"] == null))
{
try
{
Entity appointment = new Entity("appointment");
appointment.Attributes.Add("subject", "Opened automatically");
appointment.Attributes.Add("description", "Just Checking");
appointment.Attributes.Add("el_serviceappointment_id", new EntityReference("serviceappointment", serviceAppontment.Id));
appointment.Attributes.Add("scheduledstart", DateTime.Now.AddDays(7));
appointment.Attributes.Add("scheduledend", DateTime.Now.AddDays(7));
obj.OrganizationService.Create(appointment);
}
catch (Exception ex)
{
Logger.WriteException(ex);
}
}
else if (((int)(serviceAppontment.Attributes["statecode"]) == 3) && (serviceAppontment.Attributes["el_meeting_in_outlook_id"] != null))
{
//TODO
}
}
}
}
}
I don't know what to write in the second section that is supposed to update the appointment. I tried to search the web but with no success.
Can you please help?
Where you have defined the registered events, you have to put "serviceappointment", that is the entity logical name, instead of null.
Then replace: (serviceAppontment.Attributes.Contains("statecode")) || ((int)(serviceAppontment.Attributes["statecode"]) == 3) by (serviceAppontment.Attributes.Contains("statecode")) && ((OptionSetValue)(serviceAppontment.Attributes["statecode"]).Value == 3), because the field "statecode" is an OptionSet. Also replace the || by &&, because when serviceAppontment.Attributes.Contains("statecode")) is false, ((OptionSetValue)(serviceAppontment.Attributes["statecode"]).Value will throw an NullReferenceException.
To update an existing appointment, looks like there is an lookup in appointment entity to serviceappointment entity. So, you have to retrieve all the appointments related with the serviceappointment. You can use this query:
QueryExpression queryExp = new QueryExpression
{
EntityName = "appointment",
ColumnSet = new ColumnSet("subject", "description", "scheduledstart", "scheduledend"),
Criteria = new FilterExpression
{
Conditions = { new ConditionExpression("el_serviceappointment_id", ConditionOperator.Equal, serviceAppontment.Id) }
}
};
EntityCollection collection = obj.OrganizationService.RetrieveMultiple(queryExp);
if (collection.Entities.Count > 0)
{
// now that you have all the appointments related with the serviceappoitement
// you can update de any appointment you want
obj.OrganizationService.Update(appointment);
}
To update your record with a value in a lookup field in serviceappoitnment to may retrieve the serviceappoitment record Entity svcApp = obj.OrganizationService.Retrieve(serviceAppontment.LogicalName, serviceAppontment.Id, new ColumnSet("<lookup_field_in_serviceappoitnment>");
You need to add to the collumnset in the query expression the attribute requiredattendees, and then update the appoitment
if(appointment.Attributes.Contains("requiredattendees") == true)
{
appointment.Attributes["requiredattendees"] = svcApp.Attributes["<lookup_field_in_serviceappoitnment>"];
}
else
{
appointment.Attributes.Add("requiredattendees", svcApp.Attributes["<lookup_field_in_serviceappoitnment>");
}
Related
I am trying to update the "Modified By" field based on a text field called "Prepared By", which contains the name of a user. I've created a pre-operation plug-in to do this and believe I am close to done. However, the "Modified By" field is still not successfully getting updated. I am relatively new to coding and CRM, and could use some help modifying the code and figuring out how I can get this to work.
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Linq;
namespace TimClassLibrary1.Plugins
{
public class CreateUpdateContact : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = factory.CreateOrganizationService(context.UserId);
tracingService.Trace("Start plugin");
tracingService.Trace("Validate Target");
if (!context.InputParameters.Contains("Target") || !(context.InputParameters["Target"] is Entity))
return;
tracingService.Trace("Retrieve Target");
var target = (Entity)context.InputParameters["Target"];
String message = context.MessageName.ToLower();
SetCreatedByAndModifiedBy(tracingService, service, target, message);
}
private void SetCreatedByAndModifiedBy(ITracingService tracingService, IOrganizationService service, Entity target, string message)
{
tracingService.Trace("Start SetPriceList");
tracingService.Trace("Validate Message is Create or Update");
if (!message.Equals("create", StringComparison.OrdinalIgnoreCase) && !message.Equals("update", StringComparison.OrdinalIgnoreCase))
return;
tracingService.Trace("Retrieve Attributes");
var createdByReference = target.GetAttributeValue<EntityReference>("new_createdby");
var modifiedByReference = target.GetAttributeValue<EntityReference>("new_modifiedby");
tracingService.Trace("Retrieve And Set User for Created By");
RetrieveAndSetUser(tracingService, service, target, createdByReference, "createdby");
tracingService.Trace("Retrieve And Set User for Modified By");
RetrieveAndSetUser(tracingService, service, target, modifiedByReference, "modifiedby");
}
private void RetrieveAndSetUser(ITracingService tracingService, IOrganizationService service, Entity target, EntityReference reference, string targetAttribute)
{
tracingService.Trace("Validating Reference");
if (reference == null)
return;
tracingService.Trace("Retrieving and Validating User");
var user = RetrieveUserByName(service, reference.Name, new ColumnSet(false));
if (user == null)
return;
tracingService.Trace("Setting Target Attribute");
target[targetAttribute] = user.ToEntityReference();
}
private Entity RetrieveUserByName(IOrganizationService service, string name, ColumnSet columns)
{
var query = new QueryExpression
{
EntityName = "systemuser",
ColumnSet = columns,
Criteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression
{
AttributeName = "fullname",
Operator = ConditionOperator.Equal,
Values = { name }
}
}
}
};
var retrieveResponse = service.RetrieveMultiple(query);
if (retrieveResponse.Entities.Count == 1)
{
return retrieveResponse.Entities.FirstOrDefault();
}
else
{
return null;
}
}
}
}
If you do get use from method Retreiveusernyname then you have to use below code
target[“modifiedby”] = new EntityRefrence(user.logicalname,user.id);
I don't see anything obviously wrong with your update, however you are taking a complicated and unnecessary step with your RetrieveUserByName() method. You already have EntityReference objects from your new_createdby and new_modifiedby fields, you can simply assign those to the target:
if (message.Equals("create", StringComparison.OrdinalIgnoreCase))
{
target["createdby"] = target["new_createdby];
}
else if (message.Equals("update", StringComparison.OrdinalIgnoreCase))
{
target["modifiedby"] = target["new_modifiedby];
}
If new_createdby and new_modifiedby are not entity references, then that would explain why your existing code does not work, if they are, then use my approach.
I have two similar plugins in Dynamics CRM 2016 ONPREMISE to merge into one.
They're
registered to the same entity,
both triggered by update message,
one plugin check value of 3 fields, the other check value of 4 fields. If all equal to a specified value, then go on. If not, return.
4.set, map or calculate the value from old record to new record. two plugins handle two sets of fields.
create a new record.
What I can think is "if else-if " structure. But it looks so naive. Anybody have any advice?
The other plugin checks 3 other fields and execute similar action creating new record with some other fields set or mapped.
Thanks,
protected void ExecuteApplication(LocalPluginContext localContext)
{
IPluginExecutionContext context = null;
IOrganizationService service = null;
ITracingService tracer = null;
context = localContext.PluginExecutionContext;
service = localContext.OrganizationService;
tracer = localContext.TracingService;
try
{
// ensure we have an application and update message
Entity application = new Entity(applicationEntityName);
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
application = (Entity)context.InputParameters["Target"];
if (!application.LogicalName.ToLower().Equals(this.applicationEntityName))
{
return;
}
}
else
{
return;
}
if (context.MessageName.ToLower() != "update")
{
return;
}
// Fetch data from PreImage
Entity postImageApplication = context.PostEntityImages["PostImage"];
//check three fields are not null
if (application.GetAttributeValue<OptionSetValue>("statuscode") == null ||
postImageApplication.GetAttributeValue<EntityReference>("new_service").Name == null ||
postImageApplication.GetAttributeValue<EntityReference>("new_source").Name == null)
{
return;
}
if (
application.GetAttributeValue<OptionSetValue>("statuscode").Value == 881780003 &&
postImageApplication.GetAttributeValue<EntityReference>("new_service").Name == "CIC"
)
// process if the update meets the criteria
{
Entity newApplication = new Entity("new_application");
// set
newApplication.Attributes.Add("new_effectiveapplication", true);
newApplication.Attributes.Add("new_confirmdate", DateTime.Now);
newApplication.Attributes.Add("new_signdate", DateTime.Now);
//mapped
if (postImageApplication.Attributes.Contains("new_client"))
{
newApplication.Attributes.Add("new_client", postImageApplication["new_client"]);
}
if (postImageApplication.Attributes.Contains("new_servicecentre"))
{
newApplication.Attributes.Add("new_servicecentre", postImageApplication["new_servicecentre"]);
}
service.Create(newApplication);
}
else
{
return;
}
I like to abstract unwieldy predicates into their own method.
How about something like this:
private bool allFieldsHaveValues()
{
return application.GetAttributeValue<OptionSetValue>("statuscode") != null
&& postImageApplication.GetAttributeValue<EntityReference>("new_service").Name != null
&& postImageApplication.GetAttributeValue<EntityReference>("new_source").Name != null;
}
private bool valuesAreValid()
{
return application.GetAttributeValue<OptionSetValue>("statuscode").Value == 881780003
&& postImageApplication.GetAttributeValue<EntityReference>("new_service").Name == "CIC";
}
if (allFieldsHaveValues() && valuesAreValid())
{
Entity newApplication = new Entity("new_application");
I have created two new fields named "Price" for quote and quote product and I want to update the second every time I update the first.
Here is my code:
protected void ExecutePostAccountUpdateContacts(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
string oldPrice = "";
string newPrice = "";
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
var ServiceContext = new OrganizationServiceContext(service);
ITracingService tracingService = localContext.TracingService;
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
Entity preImageEntity = (context.PreEntityImages != null && context.PreEntityImages.Contains(this.preImageAlias)) ? context.PreEntityImages[this.preImageAlias] : null;
// get the post entity image
Entity postImageEntity = (context.PostEntityImages != null && context.PostEntityImages.Contains(this.postImageAlias)) ? context.PostEntityImages[this.postImageAlias] : null;
if (preImageEntity.Attributes.Contains("Price"))
{
oldPrice = (string)preImageEntity.Attributes["Price"];
}
if (postImageEntity.Attributes.Contains("Price"))
{
newPrice = (string)postImageEntity.Attributes["Price"];
}
if (newPrice != oldPrice)
{
try
{
//Create query to get the related contacts
var res = from c in ServiceContext.CreateQuery("Products")
where c["parentQuoteid"].Equals(entity.Id)
select c;
foreach (var c in res)
{
Entity e = (Entity)c;
e["Price"] = newPrice;
ServiceContext.UpdateObject(e);
}
ServiceContext.SaveChanges();
}
catch (FaultException ex)
{
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
}
}
}
Although you haven't asked a question, your query isn't quite right. So I am assuming your plugin fails when querying for product with a parentquoteid.
Not all linq operators are implemented, also , pass the entity logical name to the create query as a parameter, so instead of Products, just product. There is no out of the box field called parentquoteid, are you missing your custom attribute prefix?
var res = from c in ServiceContext.CreateQuery("product")
where c.GetAttributeValue<Guid>("new_parentquoteid") == entity.Id
select c;
I created a plug-in that calculates the pricing of the quote based on custom fields whenever update done on the quote entity.I executed the plugin on pre-opertaion update of the quote entity.I tried to debbug my plugin, it retrives null values.For example the value of the field "edm_CashAmount" contains 5000 but the code retrieved null. Kindly advise on the below. Thanks in advance.
namespace CRMPlugins.Plugins
{
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk.Messages;
public class PrequoteUpdate : Plugin
{
public PrequoteUpdate()
: base(typeof(PrequoteUpdate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Update", "quote", new Action<LocalPluginContext>(ExecutePrequoteUpdate)));
}
protected void ExecutePrequoteUpdate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
Entity entity = null;
if (localContext.PluginExecutionContext.InputParameters.Contains("Target") && localContext.PluginExecutionContext.InputParameters["Target"] is Entity)
{
entity = (Entity)localContext.PluginExecutionContext.InputParameters["Target"];
}
else
{
return;
}
decimal instotal = 0;
Quote quote = entity.ToEntity<Quote>();
using (GeneratedEntities orgContext = new GeneratedEntities(localContext.OrganizationService))
{
var installements = (from b in orgContext.edm_installementSet
where b.GetAttributeValue<Guid>("edm_quote") == quote.QuoteId
select b);
foreach (var c in installements)
{
if (c.edm_Amount != null)
{
instotal += (decimal)c.new_Decimal;
}
}
}
decimal cash = 0;
if (quote.edm_CashAmount != null)
{
cash = Convert.ToDecimal(quote.GetAttributeValue<Money>("edm_cashamount").Value);
}
decimal check = 0;
if (quote.edm_CheckAmount != null)
{
check = Convert.ToDecimal(quote.GetAttributeValue<Money>("edm_checkamount").Value);
}
decimal credit = 0;
if (quote.edm_CreditCardAmount != null)
{
credit = Convert.ToDecimal(quote.GetAttributeValue<Money>("edm_creditcardamount").Value);
}
decimal gift = 0;
if (quote.new_GiftCard != null)
{
gift = Convert.ToDecimal(quote.GetAttributeValue<Money>("new_giftcard").Value);
}
decimal total = 0;
if (quote.TotalLineItemAmount != null)
{
total = Convert.ToDecimal(quote.GetAttributeValue<Money>("totallineitemamount").Value);
}
decimal currentbalane = 0;
if (quote.edm_CurrentBalane != null)
{
currentbalane = Convert.ToDecimal(quote.GetAttributeValue<Money>("edm_currentbalane").Value);
}
decimal DiscAmount = 0;
if (quote.DiscountAmount != null)
{
DiscAmount = Convert.ToDecimal(quote.GetAttributeValue<Money>("discountamount").Value);
}
decimal totalafterdiscount = total - DiscAmount;
decimal tax = (totalafterdiscount * 10) / 100;
decimal totalwithvat = totalafterdiscount + tax;
decimal paidamount = cash + check + credit + gift + instotal;
decimal remainingamount = totalwithvat - paidamount;
quote["edm_cashamount_1"] = new Money(tax);
quote["edm_totaltax"] = new Money(tax);
quote["edm_paidamount"] = new Money(paidamount);
quote["edm_remainingamount"] = new Money(remainingamount);
quote["edm_total"] = new Money(totalwithvat);
quote["edm_totalinstallements"] = new Money(instotal);
quote["edm_checkamount_1"] = new Money(totalwithvat);
}
}
}
for update plugins, if the value has not been changed then it will not appear in the target entity. Therefore you should create a pre entity image an include these values, or you can create a post entity image to see the state of the entity after the changes will be applied
I am writing crm2011 plugin in "Email" entity with "Send" Message of Pre_operation. What i want to do is when i click "Send" button in email entity, I do the necessary checking before send. If the checking is not correct, I want to prevent and stop the sending email and show "the alert message" and stop the second plugin(this plugin send email and create the associated entity to convert "Case"). Please give me some suggestion for that plugin?
Should i use pre-Validation stage or Pre_operation state? And how can I return false to stop plugin.
public void Execute(IServiceProvider serviceProvider)
{
try
{
string message = null;
_serviceProvider = serviceProvider;
_context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
_serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
_currentUser = _context.UserId;
message = _context.MessageName.ToLower();
if (message == "send")
{
if (_context.InputParameters != null && _context.InputParameters.Contains("EmailId"))
{
object objEmailId = _context.InputParameters["EmailId"];
if (objEmailId != null)
{
_emailId = new Guid(objEmailId.ToString());
FindEmailInfo();
if (_email != null)
{
if (_email.Attributes.Contains("description") && _email.Attributes["description"] != null)//Email descritpion is not null
{
string emaildescription = StripHTML();
//Find KB Article prefix no in system config entity
serviceguideprefix = "ServiceGuidesPrefix";
QueryByAttribute query = new QueryByAttribute("ppp_systemconfig");
query.ColumnSet = new ColumnSet(true);
query.AddAttributeValue(sysconfig_name, serviceguideprefix);
EntityCollection sysconfig = _service.RetrieveMultiple(query);
if (sysconfig.Entities.Count > 0)
{
Entity e = sysconfig.Entities[0];
if (e.Attributes.Contains("ppp_value"))
{
ppp_value = e.Attributes["ppp_value"].ToString();
}
}
if (ppp_value != null && ppp_value != string.Empty)
{
//var matches = Regex.Matches(emaildescription, #"KBA-\d*-\w*").Cast<Match>().ToArray();
var matches = Regex.Matches(emaildescription, ppp_value + #"-\d*-\w*").Cast<Match>().ToArray();
//ReadKBNo(emaildescription);
foreach (Match kbnumber in matches)
{
EntityCollection kbarticlecol = FindKBArticleIds(kbnumber.ToString());
if (kbarticlecol.Entities.Count > 0)
{
Entity kbariticle = kbarticlecol.Entities[0];
if (kbariticle.Attributes.Contains("mom_internalkm"))
{
bool internalserviceguide = (bool)kbariticle.Attributes["mom_internalkm"];
if (internalserviceguide) found = true;
else found = false;
}
else found = false;
}
}
}
if (found)
{
//-----
}
}
}
}
}
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException(ex.Message, ex);
}
}
Well stopping the plugin is dead easy you just throw InvalidPluginException, the message you give it will be shown to the user in a alert window. You will have to do this on the pre of the send. In this case I don't think it will matter if its pre-validation or pre-operation.
Edit:
Yes, you should throw an InvalidPluginException even if no exception has happened in code. I accept this isnt what we would normally do, but its the way its meant to work. Msdn has more details: http://msdn.microsoft.com/en-us/library/gg334685.aspx
So for example the code would look like:
public void Execute(IServiceProvider serviceProvider)
{
try
{
//This is where we validate the email send
if(emailIsOkay)
{
//Do something
}
else if(emailIsNotOkay)
{
//Throw and exception that will stop the plugin and the message will be shown to the user (if its synchronous)
throw new InvalidPluginExecutionException("Hello user, your email is not correct!!");
}
}
catch (InvalidPluginExecutionException invalid)
{
//We dont to catch exception for InvalidPluginExecution, so just throw them on
throw;
}
catch (Exception ex)
{
//This exception catches if something goes wrong in the code, or some other process.
throw new InvalidPluginExecutionException(ex.Message, ex);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Crm;
using Microsoft.Xrm.Sdk;
using System.ServiceModel;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace SendEmail
{
public class Email : IPlugin
{
public void Execute(IServiceProvider serviceprovider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceprovider.GetService(typeof(IPluginExecutionContext));
if (!(context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity))
return;
//entity
Entity ent = (Entity)context.InputParameters["Target"];
if (ent.LogicalName != "entityName")//EntityName
throw new InvalidPluginExecutionException("Not a Service Request record! ");
//service
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceprovider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService _service = serviceFactory.CreateOrganizationService(context.UserId);
string Email="";
if (ent.Contains("emailidfiled"))
Email = (string)ent["emailidfiled"];
#region email template
QueryExpression query = new QueryExpression()
{
EntityName = "template",
Criteria = new FilterExpression(LogicalOperator.And),
ColumnSet = new ColumnSet(true)
};
query.Criteria.AddCondition("title", ConditionOperator.Equal, "templateName");
EntityCollection _coll = _service.RetrieveMultiple(query);
if (_coll.Entities.Count == 0)
throw new InvalidPluginExecutionException("Unable to find the template!");
if (_coll.Entities.Count > 1)
throw new InvalidPluginExecutionException("More than one template found!");
var subjectTemplate = "";
if (_coll[0].Contains("subject"))
{
subjectTemplate = GetDataFromXml(_coll[0]["subject"].ToString(), "match");
}
var bodyTemplate = "";
if (_coll[0].Contains("body"))
{
bodyTemplate = GetDataFromXml(_coll[0]["body"].ToString(), "match");
}
#endregion
#region email prep
Entity email = new Entity("email");
Entity entTo = new Entity("activityparty");
entTo["addressused"] =Email;
Entity entFrom = new Entity("activityparty");
entFrom["partyid"] = "admin#admin.com";
email["to"] = new Entity[] { entTo };
email["from"] = new Entity[] { entFrom };
email["regardingobjectid"] = new EntityReference(ent.LogicalName, ent.Id);
email["subject"] = subjectTemplate;
email["description"] = bodyTemplate;
#endregion
#region email creation & sending
try
{
var emailid = _service.Create(email);
SendEmailRequest req = new SendEmailRequest();
req.EmailId = emailid;
req.IssueSend = true;
GetTrackingTokenEmailRequest wod_GetTrackingTokenEmailRequest = new GetTrackingTokenEmailRequest();
GetTrackingTokenEmailResponse wod_GetTrackingTokenEmailResponse = (GetTrackingTokenEmailResponse)
_service.Execute(wod_GetTrackingTokenEmailRequest);
req.TrackingToken = wod_GetTrackingTokenEmailResponse.TrackingToken;
_service.Execute(req);
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException("Email can't be saved / sent." + Environment.NewLine + "Details: " + ex.Message);
}
#endregion
}
private static string GetDataFromXml(string value, string attributeName)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
XDocument document = XDocument.Parse(value);
// get the Element with the attribute name specified
XElement element = document.Descendants().Where(ele => ele.Attributes().Any(attr => attr.Name == attributeName)).FirstOrDefault();
return element == null ? string.Empty : element.Value;
}
}
}