web
You’re offline. This is a read only version of the page.
close
Skip to main content
Community site session details

Community site session details

Session Id :
Microsoft Dynamics CRM (Archived)

CalculatePrice Plugin - V9

(2) ShareShare
ReportReport
Posted on by

I'm running into some issues trying to create a CalculatePrice Plugin around preventing it from running recursively in V9, 9.0.0.3292. Has anyone else run into this and solved it?

I'm reusing Microsoft's sample code provided here which shows the following:

Set a Shared Variable on the current context and parent context:  

context.SharedVariables.Add("CustomPrice", true);
context.ParentContext.SharedVariables.Add("CustomPrice", true);

Verify the Shared Variable isn't present with the following code:

if (context.ParentContext != null
   && context.ParentContext.ParentContext != null
   && context.ParentContext.ParentContext != null
   && context.ParentContext.ParentContext.ParentContext.SharedVariables.ContainsKey("CustomPrice")
   && (bool)context.ParentContext.ParentContext.ParentContext.SharedVariables["CustomPrice"])
   return;

In practice, I'm finding that when I do a retrieve of the target entity in the execution of my CalculatePrice plugin, the plugin is kicked off again. In the 2nd execution, the ParentContext is still the same as the initial plugin execution and it does not have the Shared Variable I set on it. I've tried setting it on a Pre-Operation and Post-Operation plugin with no luck. I still end up with an error that my plugin is kicking off an infinite loop. I should note that I don't have a try/catch around the retrieve like in the sample code.

For now, I'm able to check the depth of the context and parent context. If they're different, I can reasonably guess that this is a recursive call. I feel like this is a bit more hacky than using shared variables. I also think retrieving records with a RetrieveMultiple doesn't kick off the plugin, but I'm not positive on that.

Thanks for any help!

*This post is locked for comments

I have the same question (0)
  • catsem Profile Picture
    on at
    RE: CalculatePrice Plugin - V9

    I can confirm this issue. Good job Microsoft for chaning the API and forgetting to update the documentation...

    @ehirsch  Would you mind sharing your workaround code?

    Best Regards

    Chris

  • Suggested answer
    Adrian Begovich Profile Picture
    1,027 Moderator on at
    RE: CalculatePrice Plugin - V9

    Hi ehirsch,

    It sounds like you need to stop the Plugin from executing when the context.Depth property is greater than one.

    Try adding this code to your Execute method.

    if (context.Depth > 1)
     {
        return; 
     }

    If this does not solve your problem, you can post your code and I will point you in the right direction.

  • catsem Profile Picture
    on at
    RE: CalculatePrice Plugin - V9

    [quote user="Adrian Begovich"]

    Try adding this code to your Execute method.

    if (context.Depth > 1)
     {
        return; 
     }

    [/quote]

    This seems to work. But the sample implementation has several other issues with Version 9.x of Dynamics.

    From what I've found out so far:

    - Hierarchie/inheredety of the classes Entity and EntityReference has changed (undocumented)

    - The recursion issue mentioned here...

    - the biggest problem is that the CalculatePrice message does not seem to be triggered any more.

    You could use the update message, but this is triggered so often, that it will seriously hit the performance.

  • ehirsch Profile Picture
    on at
    RE: CalculatePrice Plugin - V9

    Below is the code I'm using. This checks if this is a nested plugin, its immediate parent context is for the same entity, and the depth has changed from the parent context.

    This code is still hacky as I don't feel that checking depth is too reliable. I'd rather be able to use a Shared Variable to stop an infinite recursive loop.

    if (context.ParentContext != null && context.ParentContext.PrimaryEntityName == context.PrimaryEntityName && 
    context.ParentContext.Depth != context.Depth) { return; }


  • catsem Profile Picture
    on at
    RE: CalculatePrice Plugin - V9

    [quote user="ehirsch"]

    Below is the code I'm using. This checks if this is a nested plugin, its immediate parent context is for the same entity, and the depth has changed from the parent context.

    This code is still hacky as I don't feel that checking depth is too reliable. I'd rather be able to use a Shared Variable to stop an infinite recursive loop.

    if (context.ParentContext != null && context.ParentContext.PrimaryEntityName == context.PrimaryEntityName && 
    context.ParentContext.Depth != context.Depth) { return; }

    [/quote]

    Thank you very much for sharing your code.

    One more question. Did you register the plugin for the CalculatePrice Message? It seems like in my case this message is not triggered any more by the backend... (at Dynamics Version 9.0.2.189)

    Very disapointing...

  • Suggested answer
    Community Member Profile Picture
    on at
    RE: CalculatePrice Plugin - V9
    [deleted]
  • Suggested answer
    Community Member Profile Picture
    on at
    RE: CalculatePrice Plugin - V9

    /// <summary>

    /// In v9.0, on preoperation of Create SDK of QOIS entity (Quote,  Opportunity, Invoice, SalesOrder) and

    /// post operation of Update, Retrieve SDK of QOIS entity, the CalculatePricePlugin is explictly called.

    /// If CalculatePricePlugin internally calls CRU Actions on QOIS entity, then we have infinite loop.

    /// </summary>

    /// <param name="context"></param>

    /// <param name="traceService"></param>

    /// <returns>Returns true, if the current PluginStep is called due to Pre Or Post Operation of CRUActions on QOIS entity</returns>

    private bool IsThisPluginStepCalledByPreOrPostOperationofCRUSDKOnQOISEntity(IPluginExecutionContext context, ITracingService traceService)

    {

    traceService.Trace("Parent: Primary Entity Name {0} and SDK Message Name {1}",

    context.ParentContext.PrimaryEntityName,

    context.ParentContext.MessageName);

    List<String> updatedentities = new List<string>(new string[] { "quote", "salesorder", "invoice", "opportunity" });

    List<String> updatedSDKMessage = new List<string>(new string[] { "Create", "Retrieve", "Update" });

    if (context.ParentContext != null)

    {

    var parentEntityName = context.ParentContext.PrimaryEntityName;

    if (updatedentities.Contains(parentEntityName))

    {

    var ParentSDKMessageName = context.ParentContext.MessageName;

    if (updatedSDKMessage.Contains(ParentSDKMessageName))

    return true;

    }

    }

    return false;

    }

    You can use above function in your execute function of plugin step. if the below function returns true, do not execute the plugin. For e.g.

    public void Execute(IServiceProvider serviceProvider)
    {

    if (IsThisPluginStepCalledByPreOrPostOperationofCRUSDKOnQOISEntity(context, traceService))
    return;

    // your code

    }

  • MRanta Profile Picture
    60 on at
    RE: CalculatePrice Plugin - V9

    Hi,

    Sorry to hijack a thread, but my issue is also related to the sample Calculate Price Plugin.  For some reason the following does not work inside the CalculateOrder method:

    ColumnSet columns = new ColumnSet();
    columns.AddColumns("totaltax", "totallineitemamount", "totalamountlessfreight", "discountamount");
    Entity order = service.Retrieve(entity.LogicalName, entity.Id, columns);

    I'm getting the following error:

    " CalculatePrice: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: An error occurred in the Calculate Price plug-in. (Fault Detail is equal to Exception details:
    ErrorCode: 0x80040265
    Message: An error occurred in the Calculate Price plug-in.; [Microsoft.Dynamics.Sales.Plugins: Microsoft.Dynamics.Sales.Plugins.PreOperationSalesOrderRetrieve]
    [cec05255-4968-e611-80e9-00155d324500: Retrieve of salesorder]
    Entered Microsoft.Dynamics.Sales.Plugins.PreOperationSalesOrderRetrieve.Execute(), Correlation Id: fe917e7c-e88b-4d50-b247-bd6774d25f15, Initiating User: 2cfe4282-0c13-e211-beae-00155d0a091c
    Exception: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: An error occurred in the Calculate Price plug-in. (Fault Detail is equal to Exception details:
    ErrorCode: 0x80040265
    Message: An error occurred in the Calculate Price plug-in.;
    [MES Solution for CRM.CustomPricing: CustomPricing.CalculatePrice]
    [e0783f62-ed2a-ea11-8b8c-00155d0a961a: CustomPricing.CalculatePrice: CalculatePrice of salesorder]"

    I'm running this against on-premise Dynamics 9.0.11.9.

    For some reason if I use "_base" the retrieve works.  Also for other attributes it seems to work.  

    Any ideas what I'm doing wrong here?

    PS Does someone know if the "default" code exists somewhere which is being used as the system calculation.  I only need to tweak a quite a small detail and would like to use the COTS code for everything else

  • Community Member Profile Picture
    on at
    RE: CalculatePrice Plugin - V9

    Are you sure the only steps you've added to the plugin assembly are of the CalculatePrice event?  Nothing on Retrieve event?

    I am using this code exactly without problem.

  • MRanta Profile Picture
    60 on at
    RE: CalculatePrice Plugin - V9

    Hi,

    I'm not attaching anything on Retrieve event.   I'm quite puzzled as well because I was testing the original MS plugin in the past as well and then it was working.  Now on 9 it does not work for me.

    But well I realized I can get the use case covered with calculated fields instead.  I will not be able to get the total to show correclty but I can create a new field instead where the total is shown right.  (The use case I'm working on is how to manage Subscription orders in Dynamics.  Pure quantity is not enough as we also need the months that the customer is buying the subscription for...  Unit price*qty*months=line total...)

    Again I wish MS would post the "default" code somewhere.   Or then there shoudl be more user friendly ways to tap into the calculation process.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Abhilash Warrier – Community Spotlight

We are honored to recognize Abhilash Warrier as our Community Spotlight honoree for…

Leaderboard > 🔒一 Microsoft Dynamics CRM (Archived)

#1
Community Member Profile Picture

Community Member 2

#1
HR-09070029-0 Profile Picture

HR-09070029-0 2

#1
UllrSki Profile Picture

UllrSki 2

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans