views:

839

answers:

2

I wrote a plugin for Dynamics 4.0 to change the value of a picklist when an opportunity entity is reopened. The picklist value is updated correctly, but the form doesn't show this until the form is closed and reopened.

Here is my plugin:

    public void Execute(IPluginExecutionContext context)
    {
        if (context.InputParameters.Properties.Contains("Target") &&
                context.InputParameters.Properties["Target"] is DynamicEntity)
        {
            ICrmService service = context.CreateCrmService(false);
            DynamicEntity entity = (DynamicEntity)context.InputParameters.Properties["Target"];
            Key key = (Key)entity.Properties["opportunityid"];

            DynamicEntity DynamicOpportunity = GetOpportunity(service, key.Value);
            Picklist StageCodePicklist = (Picklist)DynamicOpportunity.Properties["salesstagecode"];
            StageCodePicklist.IsNull = false;
            StageCodePicklist.IsNullSpecified = false;
            StageCodePicklist.name = "Advocating - Advanced (90%)";
            StageCodePicklist.Value = 200004;

            DynamicOpportunity.Properties["salesstagecode"] = StageCodePicklist;
            service.Update(DynamicOpportunity);
        }
    }

The information I assign to properties on StageCodePicklist was derived from the following query run against the database:

select * from stringmap where attributename='salesstagecode'

To reiterate, I reopen an opportunity and the salesstagecode is correctly updated, but the form displays the old value. Closing the form and reopening it for the same opportunity shows that the new value was indeed in the database.

I almost wonder if this is a bug with CRM - surely the form should display the updated value without having to close and reopen the form. But that aside, is there anything I can do to accommodate so users don't have to do this to see the updated value rather than the old value?

+1  A: 

Have you registered this on the pre or post stage?

Focus
this is registered on the post stage
splatto
Try running this against the Pre-stage instead. Typically running the plugin against a post will make the form refresh, but I'm not sure how it's handled against the reopening of an opportunity. I imagine that the main opp form gets refreshed before the post event gets fired.
Focus
After your initial question I did try this. Unfortunately it has not resolved the issue.
splatto
I'd submit a support request to Microsoft as it sounds there's something strange going on here.
Focus
Check this out, it looks like it may be the answer. But do you know how I would register this code? I've only edited the ISV file once to add a button to an entity form that executed a workflow but I'm not sure how I would implement this http://a33ik.blogspot.com/2009/05/page-refresh.html
splatto
It looks like that code goes on the onLoad of the form. It looks up the value from the database and compares it to the one on the current form. If the value is different, then it refreshes the form. You can, however, ignore the timer section of the code as it looks like it is constantly polling CRM to see if the value has changed. All you need to implement is the first section where you grab the value from the server and compare it to the current value on the form. Then just do something like window.location = window.location if they're not equal.
Focus
+2  A: 

Regardless of if you register this in a pre-stage or a post-stage it should be reflected when the form reloads. The only thing that would delay the update is if you registered your plugin to run asynchronously, in which case it runs in the background Async Service.

Which mode are you registering the plugin step as? (1=Asynchronous, 0=Synchronous).

In addition, if you register your plugin to run in the pre-stage and synchronously you can get rid of a lot of the code by just updating the target input parameter.

public void Execute(IPluginExecutionContext context)
{
    if (context.InputParameters.Properties.Contains("Target") &&
        context.InputParameters.Properties["Target"] is DynamicEntity)
    {
        DynamicEntity opp = (DynamicEntity)context.InputParameters["Target"];
        opp["salesstagecode"] = new Picklist(200004);
    }
}

Hope this helps!

Corey O'Brien
Thanks Corey. I am running this synchronously, registered pre stage. I have incorporated your suggested code and it still has the same problem. The value is updated, but the reloaded form doesn't show this. Only when the form is manually refreshed a second time (F5) or when the form is closed then reopened does the new value show
splatto
I wonder if I can force a refresh via the SDK? That might be an adequate workaround if there is no other way about this
splatto
There is definitely something odd here. This is the kind of thing we do daily. Just to make sure I have the steps correct, you: open the opp form, modify some values, click save, and then the form comes back without your plugins changes being shown?
Corey O'Brien
Close.open the opp form, run a custom workflow that reopens the opportunity. It checks the name and value of the salesstagecode picklist on the opp being reopened, and if it was set to 200004 ("Win / Closed (100%)") it alters its value to 200003 ("Final Stages (90%)"). The form displays the old value in the picklist unless the user presses F5 to reload the form. This is the behaviour regardless if the step is registered pre or post stage.
splatto
Check this out, it looks like it may be the answer. But do you know how I would register this code? I've only edited the ISV file once to add a button to an entity form that executed a workflow but I'm not sure how I would implement this http://a33ik.blogspot.com/2009/05/page-refresh.html
splatto
The issue you are running into is that workflows are always run asynchronously. So if you were to kick off your workflow and then programmatically reload the form, it could be too soon (the workflow may not be completed, or even started at that point). Do you *need* to use a workflow? Could you just have them reopen the opp with the normal menu item and then have a plugin tweak the opp? That would all run synchronously.
Corey O'Brien
The code you linked to could work in this scenario, as closed opps are read only. I'd be careful not to try to refresh a form that someone is in the middle of editing. If you want to add that code, you can put it in the form's onload event, which you can get to via the form designer.
Corey O'Brien
Sorry, I should have been clearer. the workflow (async) reopens the opp. When the opp reopens, a plugin (sync)checks the name and value of the salesstagecode picklist, etc etc
splatto
Right, but the issue is that you initiate the workflow from the form, and it should not reload the form because you scheduled a workflow to run. You can play some game with javascript to try to detect and reload the form yourself, but you're probably better off without the workflow in this case.
Corey O'Brien