locked
CRM 2013 Plugin: Change Option Set RRS feed

  • Question

  • On the form new_contractreview I have an option set field called new_contractstatus. When the user submits the data from this form, an Update plugin runs that takes the data and writes it to a file

    I want to add an IF statement to the plugin that checks whether the file has been created and populated successfully. If it has not been created correctly then it sets the contractstatus to the Pending option (100000000) and then output an error message. How would I go about doing this part of the condition? Not sure how to update the option set or how to output an error message without throwing an exception.

    Shown below is what I have so far...

    if (CSVFile != null)
    {
        AddressPath = "FM-SSO" + "_" + accountCode;
        string AddressSavePath = @"\\fm\CRMdata\maesteg\" + AddressPath + ".csv";
        System.IO.File.WriteAllText(AddressSavePath, CSVFile.ToString());
        CSVFile = "";
    }
    else
    {
        throw new Exception ("Error: File could not be created. Order was not exported.");
    }

    Tuesday, July 14, 2015 9:09 AM

All replies

  • Any help greatly appreciated!
    Tuesday, July 14, 2015 1:35 PM
  • It would be something depending on how your plugin is written along the lines of.

    It depends on the type of workflow you are running, is it pre or post etc etc.

            /// <summary>
            /// A plug-in that updates the description field with values
            /// from the unsecure and secure constructor parameters.
            /// </summary>
            /// <remarks>Register this plug-in on the Update message, of entity,
            /// pre-Operation and synchronous mode.
            /// </remarks>
        public void Execute(IServiceProvider serviceProvider)
            {
                // Obtain the execution context from the service provider.
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

                // For this sample, execute the plug-in code only while the client is online.
                if (context.IsExecutingOffline || context.IsOfflinePlayback)
                    return;

                // The InputParameters collection contains all the data passed
                // in the message request.
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    // Obtain the target entity from the Input Parameters.
                    Entity entity = (Entity)context.InputParameters["Target"];

                    if (entity.Attributes.Contains("new_contractstatus") == false)
                    {
                        entity.Attributes.Add("new_contractstatus", 100000000);
                    }
        else
        {
         //This code might be wrong.

    OptionSetValue myoptionset = new OptionSetValue();
                                                myoptionset
    .Value = 100000000; 

                      

    entity.Attributes["new_contractstatus"] = myoptionset;
        }
                }
            }


    Halldór Jóhannsson




    Tuesday, July 14, 2015 1:54 PM
  • You should also download the CRM SDK, you can find Code samples there for plugins.

    Halldór Jóhannsson

    Tuesday, July 14, 2015 1:56 PM
  • From what I can tell, the code below is the kind of functionality I'm looking for, but this code doesn't work in the plugin. Its a post-Operation synchronous plugin that runs when the "new_contractreview" form is updated using an Export button. There are no workflows on the form and I can give a full copy of the plugin code if it helps?

    else
    {
          OptionSetValue myoptionset =  new OptionSetValue();
          myoptionset.Value = 100000000; 
    
          entity.Attributes["new_contractstatus"] = myoptionset;
    }
    

    Tuesday, July 14, 2015 2:57 PM
  • A full code copy of the function this code is in would help yes.

    Halldór Jóhannsson

    Tuesday, July 14, 2015 3:38 PM
  • using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Threading.Tasks;
    using System.Text.RegularExpressions;
    
    using Microsoft.Xrm.Sdk;
    using Microsoft.Crm.Sdk;
    using Microsoft.Xrm.Sdk.Query;
    using Microsoft.Xrm.Sdk.Messages;
    using Microsoft.Xrm.Sdk.Metadata;
    using Microsoft.Xrm.Sdk.Client;
    using Microsoft.Xrm.Sdk.Linq;
    
    using System.Web;
    using System.Web.UI;
    using Microsoft.Crm.Sdk.Messages;
    
    
    namespace SalesOrder
    {
        public class OrderPlugin : IPlugin
        {
            // Declare variables
            string callOffStatus;
            string CSVFile;
            string productid;
            string quantity;
            string amount;
            string date;
            string description;
    
            string chargeDescription;
            string chargeAmount;
            string CSVFile1;
    
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    
    
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    
                // The InputParameters collection contains all the data passed 
                // in the message request.
                if (context.InputParameters.Contains("Target") &&
                    context.InputParameters["Target"] is Entity)
                {
                    Entity entity = (Entity)context.InputParameters["Target"];
                    // Issue with plugin firing when not needed, new_quotecopyid is in the quote entity not sales order therefore resolves the issue
                    if (entity.Attributes.Contains("new_quotecopyid"))
                    {
                        return;
                    }
                    else
                    {
                        // Obtain the target entity from the Input Parameters.
                        Entity contractStatusImage = (Entity)context.PostEntityImages["ContractStatus"];
                        // Retrieve value from option set 
                        var ContractReviewStatus = ((Microsoft.Xrm.Sdk.OptionSetValue)(contractStatusImage.Attributes["new_contractstatus"])).Value.ToString();
    
                        // Only want the plugin to fire under certain condition, before hand when the 'Export To FM' button is pressed JS will change the option set value to 100000001. No other code will change the value of the option set therefore
                        // When a normal save executes the plugin will never be fired
    
                        // 100000001 = SENDING
                        if (ContractReviewStatus == "100000001")
                        {
                            // Retrieve the Images we stated in the plugin registration tool
                            Entity OrderNumberImage = (Entity)context.PostEntityImages["OrderNumberImage"];
    
                            // Use the above to retrieve the required data from the lookup
                            var orderNumber = ((Microsoft.Xrm.Sdk.EntityReference)(OrderNumberImage.Attributes["new_salesorderlookup"]));
                            // Retrieves the attributes from the entity the lookup corespondes too (enables us to select any attribute within the entity)
                            var orderNumberDetails = service.Retrieve(orderNumber.LogicalName, orderNumber.Id, new ColumnSet(true));
                            // Retrieve the customer order reference
                            var customerorderRef = orderNumberDetails["new_customerorderreference"].ToString();
                            // Retrieve the order number 
                            var actualOrderNumber = orderNumberDetails["new_neworderid"].ToString();
                            // Within the sales order we have a lookup to the customer's Account, we can access Account attributes through the following
                            var accountID = ((Microsoft.Xrm.Sdk.EntityReference)orderNumberDetails["customerid"]);
                            // Retrieve the attributes from the Account Entity
                            var accountNumberDetails = service.Retrieve(accountID.LogicalName, accountID.Id, new ColumnSet(true));
                            // Retrieve the account number 
                            var accountCode = accountNumberDetails["accountnumber"].ToString();
                            // Retrieve the date required from sales order
                            var dateDeliveryRequiredImage = orderNumberDetails["requestdeliveryby"];
                            // Retrieve the shippingcode from the sales order
                            var shippingCode = orderNumberDetails["new_addresscode"].ToString();
                            // Added by Kyle - Retrieve the call off status from the sales order
                            string callOff = ((Microsoft.Xrm.Sdk.OptionSetValue)(orderNumberDetails.Attributes["new_calloffstatus"])).Value.ToString();
    
                            if (callOff != null)
                            {
                                if (callOff == "100000000")
                                {
                                    callOffStatus = "Agreed";
                                }
                                else if (callOff == "100000001")
                                {
                                    callOffStatus = "Firm Urgent";
                                }
                                else if (callOff == "100000002")
                                {
                                    callOffStatus = "Firm";
                                }
                                else if (callOff == "100000003")
                                {
                                    callOffStatus = "Material";
                                }
                                else if (callOff == "100000004")
                                {
                                    callOffStatus = "Forecast";
                                }
                                else
                                {
                                    callOffStatus = "Error!";
                                }
                            }
                            else
                            {
                                throw new Exception("No Call Off Status selected for the current order.");
                            }
    
                            //var callOffStatus 
                            // Retrieve the GUID of the sales order number
                            Guid salesGUID = ((EntityReference)OrderNumberImage["new_salesorderlookup"]).Id;
    
                            // FetchXML Query will retrieve product details from different entities, Link-entity is where the different entites used are bought in
                            // Condition Attribute is used to only select the products that is in the Grid on the Order Form
                            string fetchxml = @"
                                <fetch distinct='false' mapping='logical' output-format='xml-platform' version='1.0'>
                                <entity name='salesorderdetail'>
                                    <attribute name='productid'/>
                                    <attribute name='productdescription'/>
                                    <attribute name='priceperunit'/>
                                    <attribute name='quantity'/>
                                    <attribute name='extendedamount'/>
                                    <attribute name='salesorderdetailid'/>
                                    <attribute name='description'/>
                                    <order descending='false' attribute='productid'/>
                                        <link-entity name='product' alias='af' to='productid' from='productid'>
                                            <attribute name='name'/>
                                            <attribute name='productnumber'/>
                                        </link-entity>
                                        <link-entity name='salesorder' alias='ac' to='salesorderid' from='salesorderid'> 
                                            <filter type='and'> 
                                                <condition attribute='salesorderid' operator='eq' value='" + salesGUID + @"'/> 
                                            </filter> 
                                        </link-entity>
                                </entity>
                                </fetch>";
    
                            // Results are stored in a entity collection
                            EntityCollection result = service.RetrieveMultiple(new FetchExpression(fetchxml));
                            {
                                if (result != null && result.Entities.Count > 0)
                                {
                                    //var count = result.Entities.Count;
                                    string todaysDate = DateTime.Now.ToString("dd/MM/yyyy"); //for date ordered
    
                                    // Code is for converting UTC format into local time, uses RetrieveLocalTimeFromUTCTime function that is on bottom of code
                                    if (dateDeliveryRequiredImage != null)
                                    {
                                        DateTime dateAndTime = (DateTime)dateDeliveryRequiredImage;
                                        var localDate = RetrieveLocalTimeFromUTCTime(dateAndTime, service);
                                        date = localDate.ToString("dd-MM-yyyy");
                                    }
                                    else
                                    {
                                        date = "";
                                    }
    
                                    foreach (Entity _entity in result.Entities) // Loop through every record
                                    {
                                        productid = ((AliasedValue)_entity.Attributes["af.productnumber"]).Value.ToString(); // Retrieve product number (ID)
                                        quantity = _entity.Attributes["quantity"].ToString();
                                        description = _entity.Attributes["description"].ToString();
                                        amount = ((Money)_entity.Attributes["extendedamount"]).Value.ToString();
    
                                        // CSV file calls itself so that with every loop no data is lost
                                        CSVFile = CSVFile +
                                            "FM-SSO" + "," +
                                            "" + "," + // Room for transaction user id
                                            accountCode + "," +
                                            "" + "," + // Room for ordered by address
                                            shippingCode + "," + // Room for deliver to address
                                            "" + "," + // Room for invoice to address
                                            customerorderRef + "," +
                                            todaysDate + "," +
                                            date + "," +
                                            productid + "," +
                                            quantity + "," +
                                            amount + "," + // Room for price
                                            description + "," +
                                            actualOrderNumber + "," +
                                            "" + "," + // Room for item number
                                            "Y" + "," + // Detailed order
                                            callOffStatus + "," + // Added by Kyle - room for call off status
                                            "@";
    
                                        CSVFile = CSVFile.Replace("@", System.Environment.NewLine); // @ Used as indication of new line as normal \n function didn't work
                                    }
    
                                    string AddressPath = "FM-SSO";
    
                                    // Save CSV file
                                    // Note: When adding products to record previous Products will appear in CSV file however no duplication of orders will appear in FM
                                    if (CSVFile != null)
                                    {
                                        AddressPath = "FM-SSO" + "_" + accountCode;
                                        string AddressSavePath = @"\\fm\CRMdata\maesteg\" + AddressPath + ".csv";
                                        System.IO.File.WriteAllText(AddressSavePath, CSVFile.ToString());
                                        CSVFile = "";
                                    }
                                    else
                                    {
                                        entity["new_contractstatus"] = new OptionSetValue(100000002);
                                        throw new Exception ("Error: File could not be created. Order was not exported to Factory Master.");
                                    }
    
    
                                    // Retrieve Order Charges! This will retrieve any order charges associated with the sales order
                                    string fetchXML = @"
                                        <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
                                            <entity name='new_ordercharge'>
                                                <attribute name='createdon' />
                                                <attribute name='new_chargedescription' />
                                                <attribute name='new_amount' />
                                                <attribute name='new_orderchargeid' />
                                                <attribute name ='new_chargetext' />
                                                <order attribute='new_chargedescription' descending='false' />
                                                <link-entity name='salesorder' from='salesorderid' to='new_ordernumber' alias='ae'>
                                                <filter type='and'>
                                                    <condition attribute='salesorderid' operator='eq' value='" + salesGUID + @"'/>
                                                </filter>
                                            </link-entity>
                                            </entity>
                                        </fetch>";
    
                                    EntityCollection result1 = service.RetrieveMultiple(new FetchExpression(fetchXML));
                                    {
                                        if (result1 != null && result.Entities.Count > 0)
                                        {
                                            foreach (Entity _entity in result1.Entities) // Loop through every record
                                            {
                                                chargeDescription = _entity.Attributes["new_chargetext"].ToString();
                                                chargeAmount = _entity.Attributes["new_amount"].ToString();
    
                                                CSVFile1 = CSVFile1 +
                                                "FM-SOCHG" + "," +
                                                "" + "," + // Room for transaction user id
                                                actualOrderNumber + "," +
                                                chargeDescription + "," +
                                                chargeAmount + "," +
                                                "" + "," + // Room for VAT Code
                                                "" + "," + // Room for nominal code
                                                "" + "," + // Room for cost centre code
                                                "" + "," + // Room for department code
                                                "" + "," + // Room for onvoice per delivery
                                                "@";
                                                CSVFile1 = CSVFile1.Replace("@", System.Environment.NewLine); // @ Used as indication of new line as normal \n function didn't work
                                            }
                                            
                                            // Error:   CSVFile1 = null causing CRM form to crash at runtime.
                                            // Fix:     Added IF statement to prevent the code running if the value is null.
                                            if (CSVFile1 != null)
                                            {
                                                // Create a seperate CSV file
                                                string AddressPath1 = AddressPath + "FM-SOCHG" + "_" + accountCode;
                                                string AddressSavePath1 = @"\\fm\CRMdata\maesteg\" + AddressPath1 + ".csv";
                                                System.IO.File.WriteAllText(AddressSavePath1, CSVFile1.ToString());
                                                CSVFile1 = "";
                                            }
                                            else
                                            {
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
    
            // Code taken from Microsoft Website for conveting Time into Local Time
            // Needed as without the date was always one day behind what was selected in CRM
            private DateTime RetrieveLocalTimeFromUTCTime(DateTime utcTime, IOrganizationService service)
            {
                int? timeZoneCode = RetrieveCurrentUsersSettings(service);
    
                if (!timeZoneCode.HasValue)
                    throw new Exception("Can't find time zone code");
    
                var request = new LocalTimeFromUtcTimeRequest
                {
                    TimeZoneCode = timeZoneCode.Value,
                    UtcTime = utcTime.ToUniversalTime()
                };
    
                var response = (LocalTimeFromUtcTimeResponse)service.Execute(request);
    
                return response.LocalTime;
            }
    
            private int? RetrieveCurrentUsersSettings(IOrganizationService service)
            {
                var currentUserSettings = service.RetrieveMultiple(
                new QueryExpression("usersettings")
                {
                    ColumnSet = new ColumnSet("localeid", "timezonecode"),
                    Criteria = new FilterExpression
                    {
                        Conditions =
                			{
                    			new ConditionExpression("systemuserid", ConditionOperator.EqualUserId)
                			}
                    }
                }).Entities[0].ToEntity<Entity>();
    
                return (int?)currentUserSettings.Attributes["timezonecode"];
            }
        }
    }
    // End of plugin

    Tuesday, July 14, 2015 3:43 PM
  • see if this code helps any.       

            public void Execute(IServiceProvider serviceProvider)
      {
                // Obtain the execution context from the service provider.
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

                // The InputParameters collection contains all the data passed in the message request.
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    // Obtain the target entity from the input parameters.
                    Entity entity = (Entity)context.InputParameters["Target"];

                    try
                    {
         if (CSVFile != null)
         {
          AddressPath = "FM-SSO" + "_" + accountCode;
          string AddressSavePath = @"\\fm\CRMdata\maesteg\" + AddressPath + ".csv";
          System.IO.File.WriteAllText(AddressSavePath, CSVFile.ToString());
          CSVFile = "";

          // Check if the record has an ID
          if (context.OutputParameters.Contains("id"))
          {
           //Get the guid of the ContractReview record
           Guid regardingobjectid = new Guid(context.OutputParameters["id"].ToString());
           
           // Obtain the organization service reference.
           IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
           IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
           
           //Check the spelling on the entity name, it is case sensitive
           Entity entity = new Entity("new_contractreview");
           //Need to get the entity Id in somewhere, might be in the service.Update(entity); function itself...
           entity.id = context.OutputParameters.Contains("id");
           
           //This code might be wrong.
           OptionSetValue myoptionset =  new OptionSetValue();
           myoptionset.Value = 100000000;
           entity.Attributes["new_contractstatus"] = myoptionset;


           // Update the ContractReview Record
           service.Update(entity);
          }
         }
         else
         {
          throw new Exception ("Error: File could not be created. Order was not exported.");
         }
                    }
                    catch (FaultException<OrganizationServiceFault> ex)
                    {
                        throw new InvalidPluginExecutionException("An error occurred in the FollupupPlugin plug-in.", ex);
                    }
                    catch (Exception ex)
                    {
                        tracingService.Trace("FollowupPlugin: {0}", ex.ToString());
                        throw;
                    }
                }
            }


    Halldór Jóhannsson


    Tuesday, July 14, 2015 3:46 PM
  • You will probably have to fix something here.
    namespace SalesOrder
    {
        public class OrderPlugin : IPlugin
        {
            // Declare variables
            string callOffStatus;
            string CSVFile;
            string productid;
            string quantity;
            string amount;
            string date;
            string description;
    
            string chargeDescription;
            string chargeAmount;
            string CSVFile1;
    
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    
    
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    
                // The InputParameters collection contains all the data passed 
                // in the message request.
                if (context.InputParameters.Contains("Target") &&
                    context.InputParameters["Target"] is Entity)
                {
                    Entity entity = (Entity)context.InputParameters["Target"];
                    // Issue with plugin firing when not needed, new_quotecopyid is in the quote entity not sales order therefore resolves the issue
                    if (entity.Attributes.Contains("new_quotecopyid"))
                    {
                        return;
                    }
                    else
                    {
                        // Obtain the target entity from the Input Parameters.
                        Entity contractStatusImage = (Entity)context.PostEntityImages["ContractStatus"];
                        // Retrieve value from option set 
                        var ContractReviewStatus = ((Microsoft.Xrm.Sdk.OptionSetValue)(contractStatusImage.Attributes["new_contractstatus"])).Value.ToString();
    
                        // Only want the plugin to fire under certain condition, before hand when the 'Export To FM' button is pressed JS will change the option set value to 100000001. No other code will change the value of the option set therefore
                        // When a normal save executes the plugin will never be fired
    
                        // 100000001 = SENDING
                        if (ContractReviewStatus == "100000001")
                        {
                            // Retrieve the Images we stated in the plugin registration tool
                            Entity OrderNumberImage = (Entity)context.PostEntityImages["OrderNumberImage"];
    
                            // Use the above to retrieve the required data from the lookup
                            var orderNumber = ((Microsoft.Xrm.Sdk.EntityReference)(OrderNumberImage.Attributes["new_salesorderlookup"]));
                            // Retrieves the attributes from the entity the lookup corespondes too (enables us to select any attribute within the entity)
                            var orderNumberDetails = service.Retrieve(orderNumber.LogicalName, orderNumber.Id, new ColumnSet(true));
                            // Retrieve the customer order reference
                            var customerorderRef = orderNumberDetails["new_customerorderreference"].ToString();
                            // Retrieve the order number 
                            var actualOrderNumber = orderNumberDetails["new_neworderid"].ToString();
                            // Within the sales order we have a lookup to the customer's Account, we can access Account attributes through the following
                            var accountID = ((Microsoft.Xrm.Sdk.EntityReference)orderNumberDetails["customerid"]);
                            // Retrieve the attributes from the Account Entity
                            var accountNumberDetails = service.Retrieve(accountID.LogicalName, accountID.Id, new ColumnSet(true));
                            // Retrieve the account number 
                            var accountCode = accountNumberDetails["accountnumber"].ToString();
                            // Retrieve the date required from sales order
                            var dateDeliveryRequiredImage = orderNumberDetails["requestdeliveryby"];
                            // Retrieve the shippingcode from the sales order
                            var shippingCode = orderNumberDetails["new_addresscode"].ToString();
                            // Added by Kyle - Retrieve the call off status from the sales order
                            string callOff = ((Microsoft.Xrm.Sdk.OptionSetValue)(orderNumberDetails.Attributes["new_calloffstatus"])).Value.ToString();
    
                            if (callOff != null)
                            {
                                if (callOff == "100000000")
                                {
                                    callOffStatus = "Agreed";
                                }
                                else if (callOff == "100000001")
                                {
                                    callOffStatus = "Firm Urgent";
                                }
                                else if (callOff == "100000002")
                                {
                                    callOffStatus = "Firm";
                                }
                                else if (callOff == "100000003")
                                {
                                    callOffStatus = "Material";
                                }
                                else if (callOff == "100000004")
                                {
                                    callOffStatus = "Forecast";
                                }
                                else
                                {
                                    callOffStatus = "Error!";
                                }
                            }
                            else
                            {
                                throw new Exception("No Call Off Status selected for the current order.");
                            }
    
                            //var callOffStatus 
                            // Retrieve the GUID of the sales order number
                            Guid salesGUID = ((EntityReference)OrderNumberImage["new_salesorderlookup"]).Id;
    
                            // FetchXML Query will retrieve product details from different entities, Link-entity is where the different entites used are bought in
                            // Condition Attribute is used to only select the products that is in the Grid on the Order Form
                            string fetchxml = @"
                                <fetch distinct='false' mapping='logical' output-format='xml-platform' version='1.0'>
                                <entity name='salesorderdetail'>
                                    <attribute name='productid'/>
                                    <attribute name='productdescription'/>
                                    <attribute name='priceperunit'/>
                                    <attribute name='quantity'/>
                                    <attribute name='extendedamount'/>
                                    <attribute name='salesorderdetailid'/>
                                    <attribute name='description'/>
                                    <order descending='false' attribute='productid'/>
                                        <link-entity name='product' alias='af' to='productid' from='productid'>
                                            <attribute name='name'/>
                                            <attribute name='productnumber'/>
                                        </link-entity>
                                        <link-entity name='salesorder' alias='ac' to='salesorderid' from='salesorderid'> 
                                            <filter type='and'> 
                                                <condition attribute='salesorderid' operator='eq' value='" + salesGUID + @"'/> 
                                            </filter> 
                                        </link-entity>
                                </entity>
                                </fetch>";
    
                            // Results are stored in a entity collection
                            EntityCollection result = service.RetrieveMultiple(new FetchExpression(fetchxml));
                            {
                                if (result != null && result.Entities.Count > 0)
                                {
                                    //var count = result.Entities.Count;
                                    string todaysDate = DateTime.Now.ToString("dd/MM/yyyy"); //for date ordered
    
                                    // Code is for converting UTC format into local time, uses RetrieveLocalTimeFromUTCTime function that is on bottom of code
                                    if (dateDeliveryRequiredImage != null)
                                    {
                                        DateTime dateAndTime = (DateTime)dateDeliveryRequiredImage;
                                        var localDate = RetrieveLocalTimeFromUTCTime(dateAndTime, service);
                                        date = localDate.ToString("dd-MM-yyyy");
                                    }
                                    else
                                    {
                                        date = "";
                                    }
    
                                    foreach (Entity _entity in result.Entities) // Loop through every record
                                    {
                                        productid = ((AliasedValue)_entity.Attributes["af.productnumber"]).Value.ToString(); // Retrieve product number (ID)
                                        quantity = _entity.Attributes["quantity"].ToString();
                                        description = _entity.Attributes["description"].ToString();
                                        amount = ((Money)_entity.Attributes["extendedamount"]).Value.ToString();
    
                                        // CSV file calls itself so that with every loop no data is lost
                                        CSVFile = CSVFile +
                                            "FM-SSO" + "," +
                                            "" + "," + // Room for transaction user id
                                            accountCode + "," +
                                            "" + "," + // Room for ordered by address
                                            shippingCode + "," + // Room for deliver to address
                                            "" + "," + // Room for invoice to address
                                            customerorderRef + "," +
                                            todaysDate + "," +
                                            date + "," +
                                            productid + "," +
                                            quantity + "," +
                                            amount + "," + // Room for price
                                            description + "," +
                                            actualOrderNumber + "," +
                                            "" + "," + // Room for item number
                                            "Y" + "," + // Detailed order
                                            callOffStatus + "," + // Added by Kyle - room for call off status
                                            "@";
    
                                        CSVFile = CSVFile.Replace("@", System.Environment.NewLine); // @ Used as indication of new line as normal \n function didn't work
                                    }
    
                                    string AddressPath = "FM-SSO";
    
                                    // Save CSV file
                                    // Note: When adding products to record previous Products will appear in CSV file however no duplication of orders will appear in FM
                                    if (CSVFile != null)
                                    {
                                        AddressPath = "FM-SSO" + "_" + accountCode;
                                        string AddressSavePath = @"\\fm\CRMdata\maesteg\" + AddressPath + ".csv";
                                        System.IO.File.WriteAllText(AddressSavePath, CSVFile.ToString());
                                        CSVFile = "";
    
                                        //Check the spelling on the entity name, it is case sensitive
                                        Entity CSVentity = new Entity("new_contractreview");
                                        //Need to get the entity Id in somewhere, might be in the service.Update(entity); function itself...
                                        CSVentity.Id = new Guid(context.OutputParameters["id"].ToString());
    
                                        //This code might be wrong.
                                        OptionSetValue myoptionset = new OptionSetValue();
                                        myoptionset.Value = 100000000;
                                        CSVentity.Attributes["new_contractstatus"] = myoptionset;
    
                                        // Update the ContractReview Record
                                        service.Update(CSVentity);
                                    }
                                    else
                                    {
                                        entity["new_contractstatus"] = new OptionSetValue(100000002);
                                        throw new Exception("Error: File could not be created. Order was not exported to Factory Master.");
                                    }
    
    
                                    // Retrieve Order Charges! This will retrieve any order charges associated with the sales order
                                    string fetchXML = @"
                                        <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
                                            <entity name='new_ordercharge'>
                                                <attribute name='createdon' />
                                                <attribute name='new_chargedescription' />
                                                <attribute name='new_amount' />
                                                <attribute name='new_orderchargeid' />
                                                <attribute name ='new_chargetext' />
                                                <order attribute='new_chargedescription' descending='false' />
                                                <link-entity name='salesorder' from='salesorderid' to='new_ordernumber' alias='ae'>
                                                <filter type='and'>
                                                    <condition attribute='salesorderid' operator='eq' value='" + salesGUID + @"'/>
                                                </filter>
                                            </link-entity>
                                            </entity>
                                        </fetch>";
    
                                    EntityCollection result1 = service.RetrieveMultiple(new FetchExpression(fetchXML));
                                    {
                                        if (result1 != null && result.Entities.Count > 0)
                                        {
                                            foreach (Entity _entity in result1.Entities) // Loop through every record
                                            {
                                                chargeDescription = _entity.Attributes["new_chargetext"].ToString();
                                                chargeAmount = _entity.Attributes["new_amount"].ToString();
    
                                                CSVFile1 = CSVFile1 +
                                                "FM-SOCHG" + "," +
                                                "" + "," + // Room for transaction user id
                                                actualOrderNumber + "," +
                                                chargeDescription + "," +
                                                chargeAmount + "," +
                                                "" + "," + // Room for VAT Code
                                                "" + "," + // Room for nominal code
                                                "" + "," + // Room for cost centre code
                                                "" + "," + // Room for department code
                                                "" + "," + // Room for onvoice per delivery
                                                "@";
                                                CSVFile1 = CSVFile1.Replace("@", System.Environment.NewLine); // @ Used as indication of new line as normal \n function didn't work
                                            }
    
                                            // Error:   CSVFile1 = null causing CRM form to crash at runtime.
                                            // Fix:     Added IF statement to prevent the code running if the value is null.
                                            if (CSVFile1 != null)
                                            {
                                                // Create a seperate CSV file
                                                string AddressPath1 = AddressPath + "FM-SOCHG" + "_" + accountCode;
                                                string AddressSavePath1 = @"\\fm\CRMdata\maesteg\" + AddressPath1 + ".csv";
                                                System.IO.File.WriteAllText(AddressSavePath1, CSVFile1.ToString());
                                                CSVFile1 = "";
    
                                                //Check the spelling on the entity name, it is case sensitive
                                                Entity CSVentity = new Entity("new_contractreview");
                                                //Need to get the entity Id in somewhere, might be in the service.Update(entity); function itself...
                                                CSVentity.Id = new Guid(context.OutputParameters["id"].ToString());
    
                                                //This code might be wrong.
                                                OptionSetValue myoptionset = new OptionSetValue();
                                                myoptionset.Value = 100000000;
                                                CSVentity.Attributes["new_contractstatus"] = myoptionset;
    
                                                // Update the ContractReview Record
                                                service.Update(CSVentity);
                                            }
                                            else
                                            {
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
    
            // Code taken from Microsoft Website for conveting Time into Local Time
            // Needed as without the date was always one day behind what was selected in CRM
            private DateTime RetrieveLocalTimeFromUTCTime(DateTime utcTime, IOrganizationService service)
            {
                int? timeZoneCode = RetrieveCurrentUsersSettings(service);
    
                if (!timeZoneCode.HasValue)
                    throw new Exception("Can't find time zone code");
    
                var request = new LocalTimeFromUtcTimeRequest
                {
                    TimeZoneCode = timeZoneCode.Value,
                    UtcTime = utcTime.ToUniversalTime()
                };
    
                var response = (LocalTimeFromUtcTimeResponse)service.Execute(request);
    
                return response.LocalTime;
            }
    
            private int? RetrieveCurrentUsersSettings(IOrganizationService service)
            {
                var currentUserSettings = service.RetrieveMultiple(
                new QueryExpression("usersettings")
                {
                    ColumnSet = new ColumnSet("localeid", "timezonecode"),
                    Criteria = new FilterExpression
                    {
                        Conditions =
                			{
                    			new ConditionExpression("systemuserid", ConditionOperator.EqualUserId)
                			}
                    }
                }).Entities[0].ToEntity<Entity>();
    
                return (int?)currentUserSettings.Attributes["timezonecode"];
            }
        }
    }
    // End of plugin


    Halldór Jóhannsson

    Tuesday, July 14, 2015 4:12 PM
  • Hi,

    Just to make sure that I get the problem here, you want to set an optionset to a value and that isn't saved?

    If that assumption is correct I'd say that the issue is that you set the value in a post stage plugin. That means that the data update phase is already passed. If you need to run this in a post stage plugin you have to update the object again and you also need to make sure you don't run into recursion.

    As a general rule it's a good thing to avoid having a plugin update the object it's running on and if possible I'm trying to make all inputs of data in pre-state plugins which means that the system takes care of the update, but it's not always an option.

    Regards.


    Rickard Norström Developer CRM-Konsulterna
    http://www.crmkonsulterna.se
    Swedish Dynamics CRM Forum: http://www.crmforum.se
    My Blog: http://rickardnorstrom.blogspot.se


    Wednesday, July 15, 2015 7:16 AM
  • @Rickard - I have the field "new_contractstatus" set up on the form "new_contractreview" using the Dynamics CRM Form Editor. The field is an optionset field which has the values:

    100000000 = Pending

    100000001 = Sending

    100000002 = Sent

    100000003 = Cancelled

    Basically when the plugin runs it takes the data from the form and exports it to another program (Factory Master). All of the code works at present but I just want it to update the optionset during runtime to show when the different steps are being undertaken as well as to reset it to pending if the process fails for any reason.

    Friday, July 17, 2015 8:58 AM
  • Right, and how is this plugin registered? Pre- or post-operation (i suppose it's on update).

    If it's registered pre-operation then the updates aren't put into the database yet so you can add fields to the context and the plöatform fixes the update.

    If it's registered post-operation, the updates are already in the database and you need to do an update of the data, in this case you also need to make sure you don't get recursive calls. I suppose that this plugin is running on an object of the new_contractreview entity so as Haldór pointed out, you need to set the id of the entity you're using as an update object, I'd set it to ((Entity)context.InputParameters["Target"]).Id,

    And the main question, what is it that doesn't work. :)

    Good Luck!


    Rickard Norström Developer CRM-Konsulterna
    http://www.crmkonsulterna.se
    Swedish Dynamics CRM Forum: http://www.crmforum.se
    My Blog: http://rickardnorstrom.blogspot.se

    Friday, July 17, 2015 9:10 AM
  • Yeah its a post-op plugin on Update. Just tried running the code that Haldór posted and I'm getting the error "Business Process Error: The given key was not present in the dictionary"
    • Edited by Kerl_J1310 Friday, July 17, 2015 9:20 AM
    Friday, July 17, 2015 9:18 AM
  • Can you let us know if the issue has been fixed?


    If my response answered your question, please "mark the response as an answer" and also "vote as helpful". Regards, Hari. www.crm2011byhari.blogspot.com

    Friday, July 17, 2015 9:50 AM
  • Can you let us know if the issue has been fixed?


    If my response answered your question, please "mark the response as an answer" and also "vote as helpful". Regards, Hari. www.crm2011byhari.blogspot.com


    No, the issue hasn't been fixed. I'm assuming the line causing the error is

    //Need to get the entity Id in somewhere, might be in the service.Update(entity); function itself...
    CSVentity.Id = new Guid(context.OutputParameters["id"].ToString());
    Friday, July 17, 2015 10:04 AM
  • These 2 lines will need to be updated to match your plugin, f.e. is the name of the entity correct ("new_contractreview")?
    We need to get the id of the entity that we are updating, id of the ("new_contractreview") entity.

    //Check the spelling on the entity name, it is case sensitive
    Entity CSVentity = new Entity("new_contractreview");
    //Need to get the entity Id in somewhere, might be in the service.Update(entity); function itself...
    CSVentity.Id = new Guid(context.OutputParameters["id"].ToString());

    The following will check if the file exists, then it will update the "new_contractreview" "new_contractstatus" field with the value 100000000.
    If you need to inform the user you could do some sort of combination between setting a boolean in the plugin on the entity then on the form have some javascript use the alert() function if the boolean is true, then set it back to false so it is only shown once.

    //If file does not exist.

    if(!File.Exists(AddressSavePath)) { //Check the spelling on the entity name, it is case sensitive Entity CSVentity = new Entity("new_contractreview"); //Need to get the entity Id in somewhere, might be in the service.Update(entity); function itself... CSVentity.Id = Entity.Id;

    //This code might be wrong. OptionSetValue myoptionset = new OptionSetValue();
    myoptionset
    .Value = 100000000;
    CSVentity.Attributes["new_contractstatus"] = myoptionset;

    // Update the ContractReview Record
    service
    .Update(CSVentity);

    }
    else
    {
    //What to do if everything is ok.
    }



    Halldór Jóhannsson

    Friday, July 17, 2015 2:14 PM
  • Okay, so if I'm understanding correctly... the line

    Entity CSVentity = new Entity("new_contractreview");

    Is correct as the value corresponds exactly to the name of the form entity. The second line,

    CSVentity.Id = new Guid(context.OutputParameters["id"].ToString());

    Needs to be corrected to match the ID value given to that of the form. Which, in this case, is "new_contractreviewid". However after changing that value in the line the code still comes up with the same error? Tried the code you gave as well as this...

    //Check the spelling on the entity name, it is case sensitive
    Entity CSVentity = new Entity("new_contractreview");
    
    CSVentity.Id = new Guid(context.OutputParameters["new_contractreviewid"].ToString());
    
    //This code might be wrong.
    OptionSetValue myoptionset = new OptionSetValue();
    myoptionset.Value = 100000000;
    CSVentity.Attributes["new_contractstatus"] = myoptionset.Value;
    
    // Update the ContractReview Record
    service.Update(CSVentity);
    Friday, July 17, 2015 2:54 PM
  • This will not work, I am not sure the Outputparameters contain this field.
    CSVentity.Id = new Guid(context.OutputParameters["new_contractreviewid"].ToString());

    Did you try it like this.
    //Need to get the entity Id in somewhere, might be in the service.Update(entity); function itself...
    CSVentity.Id = Entity.Id;


    Halldór Jóhannsson


    Friday, July 17, 2015 3:10 PM
  • Yeah I did, I got this compilation error: "Error: An object reference is required for the non-static field, method, or property 'Microsoft.Xrm.Sdk.Entity.Id.get' C:\Development\Shauns Work\Projects\Developing\SalesOrder\OrderPlugin.cs 225 48 SalesOrder"
    Friday, July 17, 2015 3:12 PM
  • Hi,

    I'd use the inputparameter object Target as an Enity and on that entity you have the id as a parameter.
    Entity ent = (Entity)context.InputParameters["Target"];
    CSVentity.Id = ent.Id;

    Regards


    Rickard Norström Developer CRM-Konsulterna
    http://www.crmkonsulterna.se
    Swedish Dynamics CRM Forum: http://www.crmforum.se
    My Blog: http://rickardnorstrom.blogspot.se

    Saturday, July 18, 2015 8:41 AM
  • Hi,

    I'd use the inputparameter object Target as an Enity and on that entity you have the id as a parameter.
    Entity ent = (Entity)context.InputParameters["Target"];
    CSVentity.Id = ent.Id;


    Tried this method and got an Invalid Argument error instead this time

    //Check the spelling on the entity name, it is case sensitive
    Entity CSVentity = new Entity("new_contractreview");
    
    Entity ent = (Entity)context.InputParameters["Target"];
    
    CSVentity.Id = ent.Id;
    //CSVentity.Id = new Guid(context.OutputParameters["new_contractreviewid"].ToString());
    
    
    
    //This code might be wrong.
    OptionSetValue myoptionset = new OptionSetValue();
    myoptionset.Value = 100000000;
    CSVentity.Attributes["new_contractstatus"] = myoptionset.Value;
    
    // Update the ContractReview Record
    service.Update(CSVentity)
    Monday, July 20, 2015 8:19 AM
  • Really lost with this piece of code. Have no idea where to go with it
    Tuesday, July 21, 2015 2:51 PM
  • Find the plugin profiler and use it to debug your code, this will allow yout to check what the problem is exactly and find the correct guid to set etc.

    http://mscrm-njl.blogspot.com/2014/05/how-to-use-plugin-profiler-to-debug.html


    Halldór Jóhannsson

    Tuesday, July 21, 2015 3:03 PM
  • Already tried that, the profiler won't accept the log's I'm getting so it won't debug. Having to debug manually using "throw new Exception();"
    Tuesday, July 21, 2015 3:33 PM
  • Have you tried remote debugging with visual studio?

    http://www.microsoft.com/en-us/download/details.aspx?id=38184


    Halldór Jóhannsson

    Tuesday, July 21, 2015 3:35 PM
  • I haven't, thought that was only for if you didn't have VS?

    Tuesday, July 21, 2015 3:39 PM
  • You install the remote debugging tools onto the server where CRM is running, that allows you to connect with visual studio to that server and remotely debug processes on the CRM server.

    Here is an how to . https://msdn.microsoft.com/en-us/library/vstudio/bt727f1t(v=vs.110).aspx


    Halldór Jóhannsson

    Tuesday, July 21, 2015 3:42 PM
  • Hi,

    Have you solved this yet? If not, is this an on-prem or online and if on-prem do you have your vs installed on the server so you can step debug or do you develop on another computer?

    Since there obviously are some issues here, perhaps you should start small. Start by having a plugin that just gets the id of the working object. If you can step debug you can see that it works or that something's wrong, if not you can write things to a file using streamwriter for example. If that works, expand the plugin by updating a text field on the incoming object if that works you should be able to do the updates that you want to do.

    Regards


    Rickard Norström Developer CRM-Konsulterna
    http://www.crmkonsulterna.se
    Swedish Dynamics CRM Forum: http://www.crmforum.se
    My Blog: http://rickardnorstrom.blogspot.se

    Tuesday, August 4, 2015 9:12 AM