Featured

Recent Posts


Something went wrong. Please refresh the page and/or try again.

Advertisements

Preserving ‘modifiedon’ During Data Migration in Dynamics 365 / Dataverse


We were working on a data migration requirement where we needed to preserve system fields like created on and modified on.

For Created On, things are straightforward. We can use the overriddencreatedon field, something we had already explored earlier here:

https://nishantrana.me/2018/10/16/using-overriddencreatedon-or-record-created-on-field-to-update-created-on-field-in-dynamics-365/

In this post, we focus on preserving the modifiedon value.

We started with a simple approach. We registered plugins on Pre-Create and Pre-Update and set the modifiedon field directly on the Target entity. This worked well for normal create and update scenarios.

Everything was working fine… until we started migrating appointment records in the completed state. On checking the plugin execution, we observed the following sequence:

Create -> Update

The pre-update plugin although firing was not updating the value of the modified on field. This was because we have Set State message firing after Update which overriding the modifiedon set in the pre create / update plugin.

So we thought of implementing a plugin on the SetState / SetStateDynamicEntity message which will trigger when they are marked as completed instead of Update. However, in the SetStateDynamicEntity message, we do not receive a Target entity. Instead, we get an EntityMoniker (EntityReference) along with State and Status values. Because of this, we cannot directly set modifiedon in a Pre-Operation plugin for SetStateDynamicEntity.

To handle this scenario, we implemented a small workaround. We created an additional dummy field (for example, new_triggerupdate). Then we registered a plugin on Post Operation of SetStateDynamicEntity and performed a simple update on this dummy field. This update triggered the Update message again, which in turn executed our pre-update plugin where we were setting the modifiedon value.

So the final execution flow became:

Create -> Update -> SetStateDynamicEntity -> Update

And in this final Update, the modifiedon value was set correctly.

After the migration was completed, we disabled or removed these plugins to avoid impacting normal system behavior.

This approach helped us handle all scenarios including create, update, and activities being marked as completed during migration.

The plugin code –

 public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = factory.CreateOrganizationService(context.UserId);

            string message = context.MessageName;
            tracingService.Trace($"Message: {message}");         
            DateTime forcedDate = new DateTime(2022, 12, 25);

            // =========================
            // CREATE & UPDATE (Pre-Op)
            // =========================
            if (message == "Create" || message == "Update")
            {
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity target)
                {
                    tracingService.Trace("Handling Create/Update");

                    // Direct override works ONLY in Pre-Operation
                    target["modifiedon"] = forcedDate;

                    tracingService.Trace("Modifiedon overridden in PreOperation.");
                }
            } 

            // =========================
            // SETSTATE (Post-Op)
            // =========================
            if (message == "SetState" || message == "SetStateDynamicEntity")
            {
                tracingService.Trace("Handling SetState");

                if (context.InputParameters.Contains("EntityMoniker"))
                {
                    EntityReference entityRef = (EntityReference)context.InputParameters["EntityMoniker"];

                    Entity updateEntity = new Entity(entityRef.LogicalName, entityRef.Id);

                    updateEntity["new_touchfield"] = forcedDate.ToLongDateString();

                    service.Update(updateEntity);

                    tracingService.Trace("Modifiedon updated via service.Update in SetState.");
                }
            }
        }

Hope it helps..

Advertisements

Reset / Restore the standard (OOTB) button in Dynamics 365 / Dataverse


We recently worked on a requirement where we customized an out-of-the-box ribbon button in Dynamics 365 — specifically, the Reactivate Lead button. We had renamed it to ‘Reactivate’ as part of an earlier customization.

Below is how the button appeared on the form after customization:

Later, we had a new requirement to hide this button completely and replace it with a custom ribbon button that implemented our own reactivation logic. However, when we tried to hide the button using Ribbon Workbench, we noticed that the Hide option was not available.

When we opened Ribbon Workbench and inspected the button, we observed that since the button was already customized, the standard options like Hide were no longer available.

While working within the same Ribbon Workbench session, we could see the ‘Uncustomize Button’ option.

However, an interesting behavior we observed is that once we closed or reopened the solution inside the Ribbon Workbench, the ‘Uncustomise Button’ option was no longer available. In that case, only the Delete option was visible.

This is expected behavior. Once an OOTB button is customized, it becomes part of the solution layer, and certain default actions like Hide are no longer directly available.

To fix this and restore the original behavior, we followed a simple approach.

We selected the customized button in Ribbon Workbench and chose the Uncustomize Button or Delete option. We then published the solution and reloaded it. Once the solution was reloaded, the button was restored to its original out-of-the-box state. And now, the Hide option was available again as expected.

This allowed us to properly hide the OOTB button and proceed with implementing our custom ribbon button.

We referred to the blog below, which helped confirm the approach: https://innovativeaj.wordpress.com/2020/09/29/bring-me-back-to-life-restoring-the-d365-ootb-button-to-default-version/

Hope it helps..

Advertisements

The Attribute with id does not exist — and Staged Metadata is still being processed (Dataverse / Dynamics 365 Issue)


Last week, we came across a strange issue while working with Dataverse metadata.

We had created a new attribute as part of our solution changes. Everything looked fine initially, and the attribute was created successfully without any errors. However, when we tried to delete that same attribute, we started getting an error saying that the attribute does not exist.

This was confusing for us because the attribute clearly existed and was visible in the system.

“The Attribute with ID doesnt not exist”

To validate further, we tried adding the same attribute to another solution. This time, we received a different error stating that the staged metadata for the attribute is still being processed.

The staged metadata for Attribute is still being processed, please wait before you can do any update/delete/retrieve operations.

At this point, it was clear that this was not a normal behavior. It felt like the attribute was stuck in an intermediate state where it was created but not fully available for operations.

We checked the Known Issues list in the Power Platform Admin Center and found a matching issue: https://admin.powerplatform.microsoft.com/knownissues/6269936

We applied the suggested fix mentioned there, but it did not work immediately for us. Instead of trying multiple workarounds, we decided to wait for some time and raised a support ticket.

After a couple of hours, we retried the same operations. This time, both deleting the attribute and adding it to another solution worked without any issues.

The key takeaway from this experience is simple.

If we encounter errors like: – Attribute does not exist (even though it does) – Staged metadata is still being processed

It is worth giving the system some time before trying again and/or raising a support ticket in parallel instead of wasting time trying different options to fix it.

Hope it helps..

Advertisements

Multiple Active Business Process Flow Instances for a record in Dynamics 365 / Dataverse


We recently worked on a requirement where we had to sync Business Process Flow (BPF) data between two different Dataverse environments for the Case (Incident) table. At first glance, the requirement looked straightforward — pick the active BPF instance and replicate it. However, while analyzing the source environment, we encountered an interesting and unexpected scenario.

For certain Case records, we found that there were multiple active Business Process Flow instances (of the same BPF) present for the same record.

Below is an example where we observed two active BPF instances for the same Case record:

Below is our Case record with Research as the active stage.

As we know, Dataverse is designed to maintain only one active BPF instance per record. So naturally, this raised a question — which one should we consider during synchronization?

On further analysis, we observed a consistent pattern. One BPF instance was typically created at the time when the Case record itself was created. The second instance — usually the one with the most recent Modified On value — corresponded to the latest process applied.

Based on this observation, we decided to use the following approach during synchronization:

For records with multiple active BPF instances, we pick the instance with the most recent Modified On value and ignore the older ones. This ensures that we are syncing the most relevant and currently active business process state.

Naturally, we wanted to understand how such a scenario could even exist, so we tried to replicate it. We attempted to create another BPF instance programmatically using the SDK. The code executed successfully and even returned a GUID; however, interestingly, the GUID was always the same as the already existing active instance.

This behavior clearly indicates that the platform prevents creating duplicate active instances through standard SDK operations.

After further experimentation, we discovered that the only way we were able to create multiple active BPF instances was by directly updating the Incident lookup (incidentid) on an existing BPF instance record. By reassigning the BPF instance from one Case record to another, we effectively bypassed the normal BPF lifecycle validations. This resulted in multiple active BPF instances being associated with the same Case record.

During data migration or synchronization scenarios, it is important to handle such anomalies carefully. In our case, choosing the BPF instance with the latest Modified On value ensured that we always picked the most relevant process state.

Hope it helps..

Advertisements
Advertisements

“Transaction not started. There is no active transaction” error (Dynamics 365 / Dataverse)


We recently ran into an interesting and slightly frustrating issue while trying to mark an activity (Appointment/Phone Call/ Task) as Completed in Dynamics 365.

Whenever we tried to mark the activity as completed, we were getting the following error. We were only getting the exception when the activity was owned by a Team instead of a User.

Error Code: 0x80040251 Message: “There is no active transaction. This error is usually caused by custom plug-ins that ignore errors from service calls and continue processing.”

At this point, we were quite confident that this was related to some custom logic interfering with the transaction pipeline. The error message itself clearly hinted towards plug-ins swallowing exceptions and continuing execution.

So, we started with the usual debugging checklist:

Checked all synchronous plug-ins on Activity, Appointment, and related entities. Disabled custom plug-ins one by one. Looked into ownership/team-related logic. Assigned System Admin role to the Team, etc.

Surprisingly, even after disabling all plug-ins, the issue was still occurring. That was our first big clue that something else was at play.

After wasting good enough time, we shifted our attention towards workflows and custom workflow activities. And that’s where things got interesting.

We found a custom workflow activity that had a try-catch block implemented like this:

The exception was being caught… but not thrown again. Essentially, the workflow activity was swallowing the exception silently and allowing execution to continue.

This behavior breaks the transaction pipeline. Dynamics expects failures to bubble up properly so that the transaction can be rolled back. When exceptions are consumed like this, the platform ends up in an inconsistent state, which is why we see errors like ‘There is no active transaction’.

We started first by updating the code to rethrow the exception, that’s where we realized the actual error – which was a SystemUser record does not exist. Basically in our code we were assigning Team Guid’s to a lookup of type System User causing this issue.

After getting to know the exact issue, we updated our logic accordingly to fix the issue.

Key takeaway from this experience:

We should never suppress exceptions in plug-ins or custom workflow activities without proper handling. If something fails in the pipeline, it is better to let it fail cleanly rather than leaving the system in a broken transactional state.

Hope it helps..

Advertisements

Plugin Registration Tool Login with Multi-Factor Authentication (MFA) – Uncheck “Show Advanced”


If we’re logging into the Plugin Registration Tool using an account protected with Multi-Factor Authentication (MFA), there’s one small setting that can cause login failures — Show Advanced.

We need to make sure “Show Advanced” is unchecked before clicking Login. When this option is selected, the tool exposes legacy Username and Password fields, which do not support modern Azure AD MFA authentication. Leaving it unchecked forces the tool to open the modern Microsoft login prompt, where we can complete your MFA challenge successfully.

Clicking on Login.

Microsoft also mentions this behavior in the official documentation under the plugin registration tutorial.

Reference:

Microsoft Learn – Register a plug-in

https://learn.microsoft.com/en-us/power-apps/developer/data-platform/tutorial-write-plug-in#register-plug-in

Hope it helps..

Advertisements

Nishant Rana's Weblog

Everything related to Microsoft .NET Technology

Skip to content ↓