Last week I posted about “Dataverse: Create Console For Debugging Plugin Code” and the author of the great FakeXrmEasy – Jordi Montaña Vázquez mentions about XrmRealContext which can simplify last week’s solution (for those who don’t know FakeXrmEasy, it is a Unit Testing framework for Dataverse! You can check the documentation about what it can do in here).

So here is the improvement from last week’s code!
From the Debugging project, you need to install FakeXrmEasy NuGet packages using the below command:
NuGet\Install-Package FakeXrmEasy.9
Below code is the existing code for Debugging project:
using System;
using System.IO;
using System.Text;
using DemoPlugin;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Extensions;
using Microsoft.Xrm.Sdk.PluginTelemetry;
using Microsoft.Xrm.Tooling.Connector;
using NSubstitute;
namespace DebugPlugin
{
internal class Program
{
static void Main(string[] args)
{
var connectionString = "AuthType=OAuth;Username=username;Password=password;Url=crmurl;AppId=51f81489-12ee-4a9e-aaae-a2591f45987d;RedirectUri=app://58145B91-0C36-4500-8554-080854F2AC97";
var pluginExecutionContextString = File.ReadAllText($"{Directory.GetCurrentDirectory()}//Input.json");
var pluginExecutionContext = DeserializeJsonString(pluginExecutionContextString);
var serviceProvider = Substitute.For<IServiceProvider>();
serviceProvider.Get<IPluginExecutionContext>().Returns(pluginExecutionContext);
serviceProvider.Get<IServiceEndpointNotificationService>()
.Returns(Substitute.For<IServiceEndpointNotificationService>());
serviceProvider.Get<IExecutionContext>()
.Returns(Substitute.For<IExecutionContext>());
serviceProvider.Get<ITracingService>()
.Returns(Substitute.For<ITracingService>());
serviceProvider.Get<ILogger>()
.Returns(Substitute.For<ILogger>());
var factory = Substitute.For<IOrganizationServiceFactory>();
factory.CreateOrganizationService(Arg.Any<Guid?>()).Returns((param) =>
{
var service = new CrmServiceClient(connectionString);
var userId = param.ArgAt<Guid?>(0);
if (userId != null) service.CallerId = userId.GetValueOrDefault();
return service;
});
serviceProvider.Get<IOrganizationServiceFactory>().Returns(factory);
// Execute the Plugin
new Plugin1Demo().Execute(serviceProvider);
Console.ReadKey();
}
public static RemoteExecutionContext DeserializeJsonString(string jsonString)
{
var obj = Activator.CreateInstance<RemoteExecutionContext>();
MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString));
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());
obj = (RemoteExecutionContext)serializer.ReadObject(ms);
ms.Close();
return obj;
}
}
}
Then, because FakeXrmEasy already handles the connection and the objects needed (you may need to adjust a bit if there’s an error). Below is the result after the Debugger Project was updated using XrmRealContext:
using System;
using System.IO;
using System.Text;
using DemoPlugin;
using FakeXrmEasy;
using Microsoft.Xrm.Sdk;
namespace DebugPlugin
{
internal class Program
{
static void Main(string[] args)
{
var connectionString = "AuthType=OAuth;Username=username;Password=password;Url=crmurl;AppId=51f81489-12ee-4a9e-aaae-a2591f45987d;RedirectUri=app://58145B91-0C36-4500-8554-080854F2AC97";
var pluginExecutionContextString = File.ReadAllText($"{Directory.GetCurrentDirectory()}//Input.json");
var pluginExecutionContext = DeserializeJsonString(pluginExecutionContextString);
var context = new XrmRealContext(connectionString);
context.ExecutePluginWith<Plugin1Demo>(pluginExecutionContext.InputParameters,
pluginExecutionContext.OutputParameters, pluginExecutionContext.PreEntityImages,
pluginExecutionContext.PostEntityImages);
Console.ReadKey();
}
public static RemoteExecutionContext DeserializeJsonString(string jsonString)
{
var obj = Activator.CreateInstance<RemoteExecutionContext>();
MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString));
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());
obj = (RemoteExecutionContext)serializer.ReadObject(ms);
ms.Close();
return obj;
}
}
}
We use the ExecutePluginWith method which needs several properties from RemoteExecutionContext that we already utilize before (InputParameters, OutputParameters, PreEntityImages, and PostEntityImages).
Below is the result of today’s code:

Happy CRM-ing!