Skip to content

Instantly share code, notes, and snippets.

@ace-racer
Created April 16, 2017 05:39
Show Gist options
  • Save ace-racer/8d4aa39710b8203c10d589b967104067 to your computer and use it in GitHub Desktop.
Save ace-racer/8d4aa39710b8203c10d589b967104067 to your computer and use it in GitHub Desktop.
Code to update web resource colors on update of theme color in Dynamics 365
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System.Collections.Generic;
namespace Contoso.CrmPlugins
{
public static class Common
{
/// <summary>
/// Retrieves the entity by unique values.
/// </summary>
/// <param name="entityName">Name of the entity.</param>
/// <param name="queryColumns">The query columns.</param>
/// <param name="requiredColumns">The required columns.</param>
/// <param name="service">The service.</param>
/// <returns>The entity as per the provided parameters</returns>
public static Entity RetrieveEntityByUniqueValues(string entityName, Dictionary<string, object> queryColumns, List<string> requiredColumns, IOrganizationService service)
{
if (!string.IsNullOrWhiteSpace(entityName) && queryColumns != null && requiredColumns != null &&
service != null)
{
var query = new QueryExpression(entityName);
query.ColumnSet = new ColumnSet();
foreach (var requiredColumn in requiredColumns)
{
query.ColumnSet.AddColumn(requiredColumn);
}
foreach (var queryColumn in queryColumns)
{
query.Criteria.AddCondition(queryColumn.Key, ConditionOperator.Equal, queryColumn.Value);
}
var recordsCollection = service.RetrieveMultiple(query);
if (recordsCollection != null && recordsCollection.Entities != null &&
recordsCollection.Entities.Count > 0)
{
return recordsCollection.Entities[0];
}
}
return null;
}
}
}
using Microsoft.Xrm.Sdk;
using System;
using System.Globalization;
using System.ServiceModel;
using System.Text;
namespace Contoso.CrmPlugins
{
public class PostThemeUpdate : Plugin
{
/// <summary>
/// Alias of the image registered for the snapshot of the
/// primary entity's attributes before the core platform operation executes.
/// The image contains the following attributes:
/// Updated fields value
/// </summary>
private readonly string preImageAlias = "PreImage";
/// <summary>
/// The required theme name
/// </summary>
private readonly string requiredThemeName = "Contoso Theme";
/// <summary>
/// The CSS web resource name
/// </summary>
private readonly string cssWebResourceName = "contoso_bootstrap.css";
public PostThemeUpdate()
: base(typeof(PostThemeUpdate))
{
RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Update", "theme", new Action<LocalPluginContext>(this.ExecuteThemeUpdate)));
//// 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.
}
protected void ExecuteThemeUpdate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
IOrganizationService service = localContext.OrganizationService;
IPluginExecutionContext context = localContext.PluginExecutionContext;
ITracingService traceService = localContext.TracingService;
Entity preImageEntity = (context.PreEntityImages != null && context.PreEntityImages.Contains(this.preImageAlias)) ? context.PreEntityImages[this.preImageAlias] : null;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity && preImageEntity != null)
{
Entity targetEntity = (Entity)context.InputParameters["Target"];
try
{
var themeName = targetEntity.GetAttributeValue<string>("name");
if (preImageEntity != null)
{
if (string.IsNullOrWhiteSpace(themeName))
{
themeName = preImageEntity.GetAttributeValue<string>("name");
}
if (string.Compare(themeName, requiredThemeName, StringComparison.CurrentCultureIgnoreCase) == 0)
{
// get existing color and get new color as navigation bar color
var newThemeColor = targetEntity.GetAttributeValue<string>("navbarbackgroundcolor");
string oldThemeColor = preImageEntity.GetAttributeValue<string>("navbarbackgroundcolor");
if(!string.IsNullOrWhiteSpace(oldThemeColor))
{
var webResourceEntity = ThemeUpdateHelpers.GetWebResourceEntity(service, traceService, cssWebResourceName);
if (webResourceEntity != null)
{
if (webResourceEntity.Attributes.Contains("content"))
{
byte[] existingContentByteArray = Convert.FromBase64String(webResourceEntity.Attributes["content"].ToString());
var existingWebResourceContent = UnicodeEncoding.UTF8.GetString(existingContentByteArray);
if (!string.IsNullOrWhiteSpace(existingWebResourceContent))
{
string updatedWebResourceContent = existingWebResourceContent.Replace(oldThemeColor, newThemeColor);
byte[] updatedWebResourceContentByteArray = System.Text.Encoding.UTF8.GetBytes(updatedWebResourceContent);
var updatedWebResourceContentBase64String = Convert.ToBase64String(updatedWebResourceContentByteArray);
webResourceEntity["content"] = updatedWebResourceContentBase64String;
service.Update(webResourceEntity);
traceService.Trace("Successfully updated");
traceService.Trace("Starting web resource publish");
ThemeUpdateHelpers.PublishWebResource(service, traceService, webResourceEntity.Id);
traceService.Trace("Web resource publish completed");
}
}
}
}
}
}
}
catch (FaultException<OrganizationServiceFault> fault)
{
localContext.TracingService.Trace(string.Format(CultureInfo.CurrentCulture, "Error in Plugin : Post.{0}Entity Name : {1}{2}Error Message : {3}", Environment.NewLine, context.PrimaryEntityName, Environment.NewLine, fault.Detail.InnerFault != null ? fault.Detail.InnerFault.Message : fault.Detail.Message));
throw new InvalidPluginExecutionException(OperationStatus.Failed, fault.Message);
}
catch (Exception ex)
{
localContext.TracingService.Trace(string.Format(CultureInfo.CurrentCulture, "Error in Plugin : Post.{0}Entity Name : {1}{2}Error Message : {3}", Environment.NewLine, context.PrimaryEntityName, Environment.NewLine, ex.Message));
throw new InvalidPluginExecutionException(OperationStatus.Failed, ex.Message);
}
}
}
}
}
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
namespace Contoso.CrmPlugins.Helpers
{
public static class ThemeUpdateHelpers
{
/// <summary>
/// Gets the web resource entity.
/// </summary>
/// <param name="orgService">The org service.</param>
/// <param name="tracingService">The tracing service.</param>
/// <param name="webresourceName">Name of the webresource.</param>
/// <returns></returns>
public static Entity GetWebResourceEntity(IOrganizationService orgService, ITracingService tracingService, string webresourceName)
{
Entity webResourceEntity = null;
if(orgService != null && tracingService != null && !string.IsNullOrWhiteSpace(webresourceName))
{
webResourceEntity = Common.RetrieveEntityByUniqueValues("webresource", new Dictionary<string, object>()
{
{ "name", webresourceName }
},
new List<string>() { "name", "content" },
orgService);
}
return webResourceEntity;
}
/// <summary>
/// Publishes the web resource.
/// </summary>
/// <param name="orgService">The org service.</param>
/// <param name="tracingService">The tracing service.</param>
/// <param name="webresourceName">Name of the webresource.</param>
public static void PublishWebResource(IOrganizationService orgService, ITracingService tracingService, Guid webResourceId)
{
if(webResourceId != Guid.Empty && orgService != null && tracingService != null)
{
PublishXmlRequest publishWebResourceRequest = new PublishXmlRequest
{
ParameterXml = string.Format("<importexportxml><webresources><webresource>{0}</webresource></webresources></importexportxml>", webResourceId)
};
orgService.Execute(publishWebResourceRequest);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment