1

I have a requirement that to Encrypt the custom Field and Decrypt Automatically while viewing the case in MS Dynamics CRM online Portal. I created two Plugins one is for Encrypt at PreCaseCreate and the other is to Decrypt at PostCaseRetrieve.The Plugin for Encryption is Working fine,but plugin for decrypt is not working(which means the encrypted content is not decrypting while viewing in online portal). Below is the code for decryption

// <copyright file="PostCaseRetrieve.cs" company="">
// Copyright (c) 2016 All Rights Reserved
// </copyright>
// <author></author>
// <date>4/20/2016 1:58:24 AM</date>
// <summary>Implements the PostCaseRetrieve Plugin.</summary>
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.1
// </auto-generated>

namespace CRMCaseEntityDecryptPlugin.Plugins
{
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using System.Text;
using System.Security.Cryptography;
using Microsoft.Xrm.Sdk.Query;

/// <summary>
/// PostCaseRetrieve Plugin.
/// </summary>    
public class PostCaseRetrieve : Plugin
{
    /// <summary>
    /// Initializes a new instance of the <see cref="PostCaseRetrieve"/> class.
    /// </summary>
    public PostCaseRetrieve()
        : base(typeof(PostCaseRetrieve))
    {
        base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Retrieve", "incident", new Action<LocalPluginContext>(ExecutePostCaseRetrieve)));

        // Note : you can register for more events here if this plugin is not specific to an individual entity and message combination.
        // You may also need to update your RegisterFile.crmregister plug-in registration file to reflect any change.
    }

    /// <summary>
    /// Executes the plug-in.
    /// </summary>
    /// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
    /// <see cref="IPluginExecutionContext"/>,
    /// <see cref="IOrganizationService"/>
    /// and <see cref="ITracingService"/>
    /// </param>
    /// <remarks>
    /// For improved performance, Microsoft Dynamics CRM caches plug-in instances.
    /// The plug-in's Execute method should be written to be stateless as the constructor
    /// is not called for every invocation of the plug-in. Also, multiple system threads
    /// could execute the plug-in at the same time. All per invocation state information
    /// is stored in the context. This means that you should not use global variables in plug-ins.
    /// </remarks>
    protected void ExecutePostCaseRetrieve(LocalPluginContext localContext)
    {
        if (localContext == null)
        {
            throw new ArgumentNullException("localContext");
        }

        // TODO: Implement your custom Plug-in business logic.
        IPluginExecutionContext context = localContext.PluginExecutionContext;
        IOrganizationService service = localContext.OrganizationService;
        // The InputParameters collection contains all the data passed in the message request.
        if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
        {
            // Obtain the target entity from the input parmameters.
            Entity entity = (Entity)context.InputParameters["Target"];
            if (entity.LogicalName.ToLower().Equals("incident"))
            {
                try
                {
                    ColumnSet cols = new ColumnSet(new String[] { "title", "description", "new_phicontent" });
                    var incident = service.Retrieve("incident", entity.Id, cols);
                    if (incident.Attributes.Contains("new_phicontent"))
                    {
                        string PHIContent = incident.Attributes["new_phicontent"].ToString();
                        byte[] bInput = Convert.FromBase64String(PHIContent);

                        UTF8Encoding UTF8 = new UTF8Encoding();
                        //Encrypt/Decrypt strings which in turn uses 3DES (Triple Data Encryption standard) algorithm
                        TripleDESCryptoServiceProvider tripledescryptoserviceprovider = new TripleDESCryptoServiceProvider();

                        //Alow to compute a hash value for Encryption/Decryption
                        MD5CryptoServiceProvider md5cryptoserviceprovider = new MD5CryptoServiceProvider();

                        tripledescryptoserviceprovider.Key = md5cryptoserviceprovider.ComputeHash(ASCIIEncoding.ASCII.GetBytes("secretkey"));
                        tripledescryptoserviceprovider.Mode = CipherMode.ECB;
                        ICryptoTransform icryptotransform = tripledescryptoserviceprovider.CreateDecryptor();

                        string DecryptedText = UTF8.GetString(icryptotransform.TransformFinalBlock(bInput, 0, bInput.Length));
                        incident["new_phicontent"] = DecryptedText;
                        service.Update(incident);
                    }

                }
                catch (FaultException ex)
                {
                    throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
                }
            }
        }
    }

}

}

I tried with PreCaseRetrieve event also,but i didn't got result

Kindly Provide some solution to resolve this. Thanks in advance

Mohan Jana
  • 11
  • 3
  • Put the encryption and decryption responsibilities in a separate class and write some unit tests for it. You will soon find out what's wrong. Only use the plugin class to do the event handling. – Henk van Boeijen Apr 26 '16 at 17:39

1 Answers1

0

Leave your plugin as a post plugin.

Target object from InputParameters is the object that is sent to the client, so if you modify the target object, you modify what is sent to the client. So don't retrieve the incident and then update incident. Instead, if entity contains the new_phicontent attribute, then you know the client requested the attribute and it needs to be decrypted so decrypt the value and then update entity["new_phicontent"]. Here's the updated code:

// Obtain the target entity from the input parmameters.
Entity entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName.ToLower().Equals("incident"))
{
    try
    {
        if (entity.Attributes.Contains("new_phicontent"))
        {
            string PHIContent = entity.Attributes["new_phicontent"];
            byte[] bInput = Convert.FromBase64String(PHIContent);

            // removed for brevity

            string decryptedText = UTF8.GetString(icryptotransform.TransformFinalBlock(bInput, 0, bInput.Length));
            entity["new_phicontent"] = decryptedText;
        }
    }
    catch (FaultException ex)
    {
        throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
    }
}
Polshgiant
  • 3,595
  • 1
  • 22
  • 25
  • I unregistered **PreCaseRetrieve** plugin and modified the **PostCaseRetrieve** as mentioned above and deployed,but the content decryption is not happened – Mohan Jana Apr 21 '16 at 09:25
  • Its probably just some small bug. Debug your plugin in Visual Studio: https://blogs.msdn.microsoft.com/devkeydet/2015/02/17/debug-crm-online-plugins/ – Polshgiant Apr 21 '16 at 15:39