Override the Modified On Field Value When Reassigning Resolved Cases (Dynamics 365 for Customer Service)

Typically, when working with Dynamics 365 for Customer Service entities, you expect a certain type of behaviour. A good example of this in practice is entity record activation and the differences between Active and Inactive record types. In simple terms, you are generally restricted in the actions that can be performed against an Inactive record, most commonly being the modification of a field value. You can, however, perform actions such as deleting and reassigning records to other users in the application. The latter of these can be particularly useful if, for example, an individual leaves a business and you need to ensure that another employee requires access to old, inactive records.

When it comes to reporting on time intervals for when a record was last changed, I often – rightly or wrongly – see the Modified On field used for this purpose. This, essentially, stores the date and time of when the record was…well…last modified in the system! Since only more recent changes to the application have facilitated an alternative approach in reporting a record’s age and its current stage within a process, it is perhaps understandable why this field is often chosen when attempting to report, for example, the date on which a record was moved to Inactive status. Where you may encounter issues with this is if you are working in a similar situation highlighted above – namely, an individual leaving a business – and you need to reassign all of the inactive records owned by them. Doing either of these steps will immediately update the Modified On value to the current date and time, skewering any dependent reporting.

Fortunately, there is a way of getting around this, if you don’t have any qualms about opening up Visual Studio and putting together a plug-in in C#. Via this route, you can prevent the Modified On value of a record from being updated by capturing the original value and forcing the platform to commit this value to the database during the Pre-Operation stage of the transaction, as opposed to the date and time of when the record is reassigned. In fact, using this method, you can set the Modified On value to be whatever you want. Here’s the code that illustrates how to achieve both scenarios:

using System;
using Microsoft.Xrm.Sdk;
namespace Sample.OverrideCaseModifiedDate
{
public class PreOpCaseAssignOverrideModifiedDate : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
//Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
//Extract the tracing service for use in debugging sandboxed plug-ins
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
tracingService.Trace("Tracing implemented successfully!");
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity incident = (Entity)context.InputParameters["Target"];
Entity preIncident = context.PreEntityImages["preincident"];
//At this stage, you can either get the previous Modified On date value via the Pre Entity Image and set the value accordingly...
incident["modifiedon"] = preIncident.GetAttributeValue<DateTime>("modifiedon");
//Or alternatively, set it to whatever you want - in this example, we get the Pre Entity Image createdon value, add on an hour and then set the value
DateTime createdOn = preIncident.GetAttributeValue<DateTime>("createdon");
TimeSpan time = new TimeSpan(1, 0, 0);
DateTime newModifiedOn = createdOn.Add(time);
incident["modifiedon"] = newModifiedOn;
}
}
}
}

Now, the more eagle-eyed readers may notice that the step is configured on the Update as opposed to the Assign message, which is what you (and, indeed, I when I first started out with this) may expect. Unfortunately, because the Input Parameters of the Assign message only returns two Entity Reference objects – the incident (Case) and systemuser (User) entities, respectively – as opposed to an Entity object for the incident entity, we have no means of interfering with the underlying database transaction to override the required field values. The Update message does not suffer from this issue and, by scoping the plug-in’s execution to the ownerid field only, we can ensure that it will only ever trigger when a record is reassigned.

With the above plug-in configured, you have the flexibility of re-assigning your Case records without updating the Modified On field value in the process or expanding this further to suit whatever business requirement is needed. In theory, as well, the approach used in this example could also be applied to other what we may term “system defined fields”, such as the Created On field. Hopefully, this post may prove some assistance if you find yourself having to tinker around with inactive Case records in the future.

Related

2 Comments

Bala
on 17th April 2019 at 2:55 pm

Hello,
I have facing an issue, can you pls help me here.
I am doing data migration using Kingswaysoft. Made a package mapped all fields including Statecode, StatusCode.
When I migrate record on ‘Create’ message, I am seeing ModifiedOn/By as current datetime/user.
I wrote a plugin to set ModifiedOn/By fields with the dates/users from migrated record and registered it on Create but still I can see current users details.
What I observed is An Update event triggered which updated state, status on the created record. Because of this update I am seeing current user datetime details on ModifiedOn/By.Also I registered a plugin on Update message (Pre-Operation)as well to override modifedOn/By with historic data.
But still I can see current details only, not historic.

Why am I not able to update ModifiedOn/ModifiedBy fields from Update plugin ?

What’s the name of the entity that you are trying to import data into (I’m assuming its a system entity, not a custom one)? If you can also share an example of the code you are using within the Create plugin as well, that would help me to diagnose further.