locked
Plugin Error... Help! RRS feed

  • Question

  • Hi everyone,

    I seem to get an error "The given key was not present in the dictionary".. Seems to be sometimes happening on create and always on the update.

    I have goggled this error and it seems that I need to create a pre image on Update? I'm quite new in terms of developing Plugins so any advice would be really helpful.

    I have commented out the section of the code which includes Pre Images. However, I'm not sure if I am on the right track,

    namespace WeightedBant
    {
        using System;
        using System.Collections.ObjectModel;
        using System.Globalization;
        using System.Linq;
        using System.ServiceModel;
        using Microsoft.Xrm.Sdk;
    
        /// <summary>
        /// Base class for all Plugins.
        /// </summary>    
        public class WeightedBant : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                ITracingService trace = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    
                try
                {
                    trace.Trace("Entering the plugin");
                    //Entity preImageEntity = null;
                    //if (context.PreEntityImages.Contains("PreImage") && context.PreEntityImages["PreImage"] is Entity)
                    //{
                    //    preImageEntity = (Entity)context.PreEntityImages["PreImage"];
                    //}
                    Entity entity = (Entity)context.InputParameters["Target"];
             
    #region Populating Bant Score
                    //Declaring variables that will hold the OptionSet Values. It will be set to 0 if the user does not choose
                    trace.Trace("Storing the OptionSet Values to variables");
                    //int authorityValue;
    
                    //if (((OptionSetValue)entity.Attributes["ap_authority"]).Value != null || preImageEntity.Attributes.Contains("ap_authority"))
                    //{
                    //    authorityValue = ((OptionSetValue)entity.Attributes["ap_authority"]).Value;
                    //}
    
                    //else
                    //{
                    //    authorityValue = 0;
                    //}
                    var authorityValue = entity.Attributes.Contains("ap_authority") ? ((OptionSetValue)entity.Attributes["ap_authority "]).Value : 0;
                    var needValue = entity.Attributes.Contains("ap_need")?((OptionSetValue)entity.Attributes["ap_need "]).Value : 0;
                    var budgetValue = entity.Attributes.Contains("ap_budget")?((OptionSetValue)entity.Attributes["ap_budget "]).Value : 0;
                    var timeValue = entity.Attributes.Contains("ap_time")?((OptionSetValue)entity.Attributes["ap_time "]).Value : 0;
    
                    //Calculates the total bantScore based on the Option Set Values and populates the ap_overallscore field.
                    trace.Trace("Variables now contain Value. Calculate total");
                    int bantScore = authorityValue + needValue + budgetValue + timeValue;
    
                    trace.Trace("Populate ap_overallscore");
                    entity["ap_overallscore"] = bantScore;
    
    #endregion
    
    #region Populating Lead Rating
                    //Populating Lead Rating to Cold,Warm or Hot based on Bant Score.
                    //3 = Cold. 2 = Warm. 1 = Hot
    
                    trace.Trace("Populate Lead Rating");
                    if (bantScore < 5)
                    {
                        ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 3;
                    }
                    else if (bantScore >= 5 && bantScore <= 12)
                    {
                        ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 2;
                    }
                    else
                    {
                        ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 1;
                    }
                }
    #endregion
                catch (Exception ex)
                {
                    throw new InvalidPluginExecutionException(" CRM has encountered an error when calculating the Weighted Bant. Message: " + ex.Message + ". InnerException: " + ex.InnerException);
                }
            }
        }
    }

    Monday, April 8, 2013 8:32 AM

Answers

  • Hi,davdatong

    You should also replace the code

    ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = *;

    as

    entity["leadqualitycode"] = new OptionSetValue(*);


    微软CRM

    Thursday, April 11, 2013 10:16 AM
    Moderator

All replies

  • Hi,

    You are creating Plugin Or Custom workflow???

    Monday, April 8, 2013 9:03 AM
  • Hi,

    I am creating a plugin which calculates the Lead Rating based on four custom Option Set fields.

    Thanks

    Monday, April 8, 2013 9:13 AM
  • the error "The given key was not present in the dictionary"..

    its means the attribute you used in the plug-in where not present in the entity

    check the attribute names correctly

    debug the plug-in you easily find there the problem exactly

    http://msdn.microsoft.com/en-in/library/gg328574.aspx


    ms crm

    Monday, April 8, 2013 9:34 AM
  • Hi,

    i notice the code below have a blank space,maybe it causes the error.

    var authorityValue = entity.Attributes.Contains("ap_authority") ? ((OptionSetValue)entity.Attributes["ap_authority "]).Value : 0;
    var needValue = entity.Attributes.Contains("ap_need")?((OptionSetValue)entity.Attributes["ap_need "]).Value : 0;
    var budgetValue = entity.Attributes.Contains("ap_budget")?((OptionSetValue)entity.Attributes["ap_budget "]).Value : 0;
    var timeValue = entity.Attributes.Contains("ap_time")?((OptionSetValue)entity.Attributes["ap_time "]).Value : 0;


    微软CRM

    Monday, April 8, 2013 9:34 AM
    Moderator
  • Ahhh thank you Batistuta Cai. That fixed the problem on Create.

    However, I still get the error "The given key was not present in the dictionary" on the Update. :(

    Would I need some kind of Pre or Post image to get this working??

    Monday, April 8, 2013 9:59 AM
  • In order to fix the errors on the update,you need to create a pre Image, and get the arrtibutes from the pre Image if it does not be changed.


    微软CRM



    Monday, April 8, 2013 10:05 AM
    Moderator
  • Hi,

    you can use the fetch Xml for accessing the field value because this error occured when attribute is not found .

    Monday, April 8, 2013 10:30 AM
  • hi,

    On PreImage Update we can access only four fields of entity createdOn,CreatedBy... But we can't access all fields of entity on update. For solution you can use the fetch xml in code.

    Monday, April 8, 2013 10:36 AM
  • I'm quite confused. You are saying a PreImage wont' work and Batistuta say it will work?

    I have created a PreImage on the Update step of the Lead entity and selected all attributes in the parameter box.

    I have included this line of code but still get the same error :(. The name of the Pre Image is the same name in the code.

    if (context.MessageName.Equals("update"))
                    {
                        Entity preImageEntity = (Entity)context.PreEntityImages["PreImage"];
                        authorityValue = ((OptionSetValue)preImageEntity.Attributes["ap_authority"]).Value;
                    }
                    else
                    {
                        authorityValue = 0;
                    }

    Monday, April 8, 2013 10:55 AM
  • hi,

    Firstly you debug the code and check all the attributes which you want to access if their value exists then it will work okkk....

    Monday, April 8, 2013 11:05 AM
  • This problem usually arises:

    1. when u have made typo error in referring the schema name of any field.

    2. Or when the field you try to access/retrieve in your plugin has no value in it in the database.

    When you try to retrieve any field in plugin, you can use following:

    string criteria1 = string.Empty;

     try { criteria1 = accountObject["new_criteria1"].ToString(); }
                catch (KeyNotFoundException ex) { criteria1 = ""; }

    May be this can help you.


    Regards, Karan Mittal If you find this post helpful then please "Vote as Helpful" and "Mark As Answer".

    Monday, April 8, 2013 12:33 PM
  • Thanks everyone for your advice!

    I have managed to fix the error "the given key is not present in the dictionary". However, it seems that my plugin calculation only seems to work when I update the record twice.

    It works perfectly on create, Here is my current code:

    namespace WeightedBant
    {
        using System;
        using System.Collections.ObjectModel;
        using System.Globalization;
        using System.Linq;
        using System.ServiceModel;
        using Microsoft.Xrm.Sdk;
    
        /// <summary>
        /// Base class for all Plugins.
        /// </summary>    
        public class WeightedBant : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                ITracingService trace = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    
                try
                {
                    trace.Trace("Entering the plugin");
                    Entity preImageEntity = null;
                    Entity entity = (Entity)context.InputParameters["Target"];
                    
    
    #region Populating Bant Score
                    //Declaring variables that will hold the OptionSet Values. It will be set to 0 if the user does not choose
                    trace.Trace("Storing the OptionSet Values to variables");
                    int authorityValue;
                    int needValue;
                    int budgetValue;
                    int timeValue;
    
                    //If Plugin Exection is update
                    if (context.MessageName.Equals("Update"))
                    {
                        preImageEntity = (Entity)context.PreEntityImages["PreImage"];
                        trace.Trace("Update of Entity");
                        authorityValue = preImageEntity.Attributes.Contains("ap_authority") ? ((OptionSetValue)preImageEntity.Attributes["ap_authority"]).Value : 0;
                        needValue = preImageEntity.Attributes.Contains("ap_need") ? ((OptionSetValue)preImageEntity.Attributes["ap_need"]).Value : 0;
                        budgetValue = preImageEntity.Attributes.Contains("ap_budget") ? ((OptionSetValue)preImageEntity.Attributes["ap_budget"]).Value : 0;
                        timeValue = preImageEntity.Attributes.Contains("ap_time") ? ((OptionSetValue)preImageEntity.Attributes["ap_time"]).Value : 0;
    
                        //Calculates the total bantScore based on the Option Set Values and populates the ap_overallscore field.
                        int bantScore = authorityValue + needValue + budgetValue + timeValue;
                        entity["ap_overallscore"] = bantScore;
                        PopulateLeadRating(preImageEntity,bantScore,trace);
                    }
    
                    //Plugin execution on create
                    else
                    {
                        authorityValue = entity.Attributes.Contains("ap_authority") ? ((OptionSetValue)entity.Attributes["ap_authority"]).Value : 0;
                        needValue = entity.Attributes.Contains("ap_need")?((OptionSetValue)entity.Attributes["ap_need"]).Value : 0;
                        budgetValue = entity.Attributes.Contains("ap_budget")?((OptionSetValue)entity.Attributes["ap_budget"]).Value : 0;
                        timeValue = entity.Attributes.Contains("ap_time")?((OptionSetValue)entity.Attributes["ap_time"]).Value : 0;
    
                        //Calculates the total bantScore based on the Option Set Values and populates the ap_overallscore field.
                        int bantScore = authorityValue + needValue + budgetValue + timeValue;
                        entity["ap_overallscore"] = bantScore;
                        PopulateLeadRating(entity, bantScore, trace);
                    }
    #endregion
                }
    
                catch (Exception ex)
                {
                    throw new InvalidPluginExecutionException(" CRM has encountered an error when calculating the Weighted Bant. Message: " + ex.Message + ". InnerException: " + ex.InnerException);
                }
    
            }
    
            public void PopulateLeadRating(Entity entity, int bantScore, ITracingService trace)
            {
                #region Populating Lead Rating
                //Populating Lead Rating to Cold,Warm or Hot based on Bant Score.
                //3 = Cold. 2 = Warm. 1 = Hot
    
                trace.Trace("Populate Lead Rating");
    
    
                if (bantScore < 5)
                {
                    trace.Trace("Set to Cold");
                    ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 3;
                }
                else if (bantScore >= 5 && bantScore <= 12)
                {
                    trace.Trace("Set to Warm");
                    ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 2;
                }
                else
                {
                    trace.Trace("Set to Hot");
                    ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 1;
                }
                trace.Trace("Plugin Finished");
                #endregion
            }
        }
    }

    I am now using the Pre-Image to update my record. The Update is registered on the pre-operation stage. Strange that it only recognizes the change when I save the record twice.

    Anyone got any ideas?

    Monday, April 8, 2013 4:54 PM
  • Hi,

    Pls check if the filtering attributes is selected only "ap_authority" "needValue" "budgetValue" "timeValue" this four attributes when register the pre-operation update stage,and try the code below:

    namespace WeightedBant
    {
        using System;
        using System.Collections.ObjectModel;
        using System.Globalization;
        using System.Linq;
        using Microsoft.Xrm.Sdk;

        /// <summary>
        /// Base class for all Plugins.
        /// </summary>   
        public class WeightedBant : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                ITracingService trace = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

                try
                {
                    trace.Trace("Entering the plugin");
                    Entity preImageEntity = null;
                    if (context.PreEntityImages.Contains("PreImage") && context.PreEntityImages["PreImage"] is Entity)
                    {
                        preImageEntity = (Entity)context.PreEntityImages["PreImage"];
                    }

                    Entity entity = (Entity)context.InputParameters["Target"];

                    #region Populating Bant Score

                    var authorityValue = this.GetAttributeValue<OptionSetValue>(entity, preImageEntity, "ap_authority", new OptionSetValue(0)).Value;
                    var needValue = this.GetAttributeValue<OptionSetValue>(entity, preImageEntity, "needValue", new OptionSetValue(0)).Value;
                    var budgetValue = this.GetAttributeValue<OptionSetValue>(entity, preImageEntity, "budgetValue", new OptionSetValue(0)).Value;
                    var timeValue = this.GetAttributeValue<OptionSetValue>(entity, preImageEntity, "timeValue", new OptionSetValue(0)).Value;

                    int bantScore = authorityValue + needValue + budgetValue + timeValue;

                    entity["ap_overallscore"] = bantScore;

                    #endregion

                    #region Populating Lead Rating
                    //Populating Lead Rating to Cold,Warm or Hot based on Bant Score.
                    //3 = Cold. 2 = Warm. 1 = Hot

                    trace.Trace("Populate Lead Rating");
                    if (bantScore < 5)
                    {
                        ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 3;
                    }
                    else if (bantScore >= 5 && bantScore <= 12)
                    {
                        ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 2;
                    }
                    else
                    {
                        ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 1;
                    }
                }
                    #endregion
                catch (Exception ex)
                {
                    throw new InvalidPluginExecutionException(" CRM has encountered an error when calculating the Weighted Bant. Message: " + ex.Message + ". InnerException: " + ex.InnerException);
                }
            }

            public T GetAttributeValue<T>(Entity ent, Entity preEnt, string attributeName, T defaultValue)
            {
                if (ent.Attributes.Contains(attributeName))
                {
                    if (ent[attributeName] != null)
                    {
                        return (T)ent[attributeName];
                    }
                    else
                    {
                        return defaultValue;
                    }
                }

                if (preEnt.Attributes.Contains(attributeName))
                {
                    if (preEnt[attributeName] != null)
                    {
                        return (T)preEnt[attributeName];
                    }
                    else
                    {
                        return defaultValue;
                    }
                }

                return defaultValue;
            }
        }
    }


    微软CRM

    Tuesday, April 9, 2013 3:01 AM
    Moderator
  • Thank you for that Code Batistuta. I have adjusted it a little and got the error messages from being displayed.

    Only 1 thing that is not working now and that is updating the Lead Rating based on the value of the field. Works perfectly on Create.

    I have debugged the code and its doing exactly what it should be doing. It sets the Overall to the correct value and should be setting the correct Lead Rating.

    Here is the snippet of the code:

      if (context.MessageName.Equals("Create"))
                    {
                        PopulateLeadRating(entity, bantScore, trace, service);
                    }
                    else
                    {
                        PopulateLeadRating(preImageEntity, bantScore, trace, service);
                    }


    public void PopulateLeadRating(Entity entity, int bantScore, ITracingService trace, IOrganizationService service)
            {
                #region Populating Lead Rating
                //Populating Lead Rating to Cold,Warm or Hot based on Bant Score.
                //3 = Cold. 2 = Warm. 1 = Hot
    
                trace.Trace("Populate Lead Rating");
    
                if (bantScore < 5)
                {
                    trace.Trace("Set to Cold");
                    ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 3;
                }
                else if (bantScore >= 5 && bantScore <= 12)
                {
                    trace.Trace("Set to Warm");
                    ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 2;
                }
                else
                {
                    trace.Trace("Set to Hot");
                    ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = 1;
                }
                trace.Trace("Plugin Finished");
                #endregion
            }

    This line doesn't seem to be working on update.

      ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = *;



    • Edited by davdatong Thursday, April 11, 2013 9:08 AM
    Thursday, April 11, 2013 9:07 AM
  • Hi,davdatong

    Please replace the code

      if (context.MessageName.Equals("Create"))
                    {
                        PopulateLeadRating(entity, bantScore, trace, service);
                    }
                    else
                    {
                        PopulateLeadRating(preImageEntity, bantScore, trace, service);
                    }

    as

     PopulateLeadRating(entity, bantScore, trace, service);


    微软CRM

    Thursday, April 11, 2013 9:49 AM
    Moderator
  • Thanks Batistuta. I tried that before and I get the same error on update "The given key was not present in the dictionary".
    Thursday, April 11, 2013 10:10 AM
  • Hi,davdatong

    You should also replace the code

    ((OptionSetValue)entity.Attributes["leadqualitycode"]).Value = *;

    as

    entity["leadqualitycode"] = new OptionSetValue(*);


    微软CRM

    Thursday, April 11, 2013 10:16 AM
    Moderator
  • Many thanks Batistuta! Works perfectly now. May I ask what  the difference was between the old code and the new one? Thanks again.
    Thursday, April 11, 2013 10:26 AM
  • If entity containis the leadqualitycode attribute you can set the Value,otherwise you must new one OptionSetValue.

    微软CRM


    Friday, April 12, 2013 12:56 AM
    Moderator