diff --git a/AutoNumber-Old/AutoNumber.csproj b/AutoNumber-Old/AutoNumber.csproj
deleted file mode 100644
index 43a0d8e..0000000
--- a/AutoNumber-Old/AutoNumber.csproj
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {10E2B428-F093-400A-8F7F-38AA8BCBD434}
- {4C25E9B5-9FA6-436c-8E19-B395D2A65FAF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Library
- Properties
- Celedon
- CeledonPartners.AutoNumber
- v4.0
- 512
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
- true
-
-
- AutoNumberStrongKey.snk
-
-
-
- False
- ..\..\..\..\..\CRM 2013 SP1 R1 SDK\SDK\Bin\Microsoft.Crm.Sdk.Proxy.dll
-
-
- False
- ..\..\..\..\..\CRM 2013 SP1 R1 SDK\SDK\Bin\Microsoft.Xrm.Sdk.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/AutoNumber-Old/AutoNumberPluginConfig.cs b/AutoNumber-Old/AutoNumberPluginConfig.cs
deleted file mode 100644
index 8052e93..0000000
--- a/AutoNumber-Old/AutoNumberPluginConfig.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Runtime.Serialization;
-
-namespace Celedon
-{
- [DataContract]
- public class AutoNumberPluginConfig
- {
- [DataMember]
- public string EntityName;
-
- [DataMember]
- public string EventName;
- }
-}
diff --git a/AutoNumber-Old/CeledonExtensions.cs b/AutoNumber-Old/CeledonExtensions.cs
deleted file mode 100644
index b93e24d..0000000
--- a/AutoNumber-Old/CeledonExtensions.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-// Author: Matt Barnes (matt.barnes@celedonpartners.com)
-/*The MIT License (MIT)
-
-Copyright (c) 2015 Celedon Partners
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-// Collection of useful extension methods
-
-using System;
-using System.IO;
-using System.Text;
-using System.Runtime.Serialization;
-using System.Runtime.Serialization.Json;
-
-using Microsoft.Xrm.Sdk;
-using Microsoft.Xrm.Sdk.Query;
-
-namespace Celedon
-{
- // Helpful extentions
- // Use these and add to these to make our plugins a little shorter/cleaner/leaner
- public static class Extensions
- {
- // Used to get values from context inputparameters and outputparameters, of a specific type rather than handling the Object type in our code.
- public static bool TryGetValue(this ParameterCollection parameterCollection, string key, out T value)
- {
- object valueObj;
- if (parameterCollection.TryGetValue(key, out valueObj))
- {
- try
- {
- value = (T)valueObj;
- return true;
- }
- catch (InvalidCastException) { } // Key exists, but cast failed. Let this fall through to the default return value.
- }
-
- value = default(T);
- return false;
- }
-
- // NotNull because Plugins attached to custom Actions recieve ALL input parameters, even if they were not included in the original Action context
- public static bool TryGetValueNotNull(this ParameterCollection parameterCollection, string key, out T value)
- {
- object valueObj;
- if (parameterCollection.TryGetValue(key, out valueObj))
- {
- if (valueObj != null)
- {
- try
- {
- value = (T)valueObj;
- return true;
- }
- catch (InvalidCastException) { } // Key exists, but cast failed. Let this fall through to the default return value.
- }
- }
-
- value = default(T);
- return false;
- }
-
- // NotNull because Plugins attached to custom Actions recieve ALL input parameters, even if they were not included in the original Action context
- public static bool ContainsNotNull(this ParameterCollection parameterCollection, string key)
- {
- return parameterCollection.Contains(key) && parameterCollection[key] != null;
- }
-
- // Parse JSON string to object - CRM Online compatible
- public static T ParseJSON(this string jsonString, bool useSimpleDictionaryFormat = true)
- {
- try
- {
- DataContractJsonSerializer JsonDeserializer = new DataContractJsonSerializer(typeof(T));
- using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
- {
- return (T)JsonDeserializer.ReadObject(stream);
- }
- }
- catch
- {
- throw new InvalidDataContractException("JSON string is invalid, or could not be serialized to the specified type.");
- }
- }
-
- // Try Parse JSON string to object - CRM Online compatible
- public static bool TryParseJSON(this string jsonString, out T obj, bool useSimpleDictionaryFormat = true)
- {
- try
- {
- obj = jsonString.ParseJSON(useSimpleDictionaryFormat);
- return true;
- }
- catch
- {
- obj = default(T);
- return false;
- }
- }
-
- // Convert object to JSON string - CRM Online compatible
- public static string ToJSON(this object obj, bool useSimpleDictionaryFormat = true)
- {
- DataContractJsonSerializer JsonSerializer = new DataContractJsonSerializer(obj.GetType());
- using (MemoryStream stream = new MemoryStream())
- {
- JsonSerializer.WriteObject(stream, obj);
- return Encoding.UTF8.GetString(stream.ToArray());
- }
- }
-
- // A slightly easier way to retreive all columns
- public static Entity Retrieve(this IOrganizationService service, string entityName, Guid entityId, bool allColumns)
- {
- return service.Retrieve(entityName, entityId, new ColumnSet(allColumns));
- }
-
- // Easily convert Guid to EntityReference
- public static EntityReference ToEntityReference(this Guid id, string entityType)
- {
- return new EntityReference(entityType, id);
- }
-
- // Easily convert integer to OptionSetValue
- public static OptionSetValue ToOptionSetValue(this int value)
- {
- return new OptionSetValue(value);
- }
-
- // This is how the OOB GetService method should have been...
- public static T GetService(this IServiceProvider serviceProvider)
- {
- return (T)serviceProvider.GetService(typeof(T));
- }
- }
-}
diff --git a/AutoNumber-Old/CeledonPlugin.cs b/AutoNumber-Old/CeledonPlugin.cs
deleted file mode 100644
index f3b9ca3..0000000
--- a/AutoNumber-Old/CeledonPlugin.cs
+++ /dev/null
@@ -1,409 +0,0 @@
-// Author: Matt Barnes (matt.barnes@celedonpartners.com)
-/*The MIT License (MIT)
-
-Copyright (c) 2015 Celedon Partners
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-// Implements the Plugin Workflow Activity.
-
-using System;
-using System.Linq;
-using System.ServiceModel;
-using System.Globalization;
-using System.Collections.ObjectModel;
-using Microsoft.Xrm.Sdk;
-using Microsoft.Xrm.Sdk.Client;
-using Microsoft.Xrm.Sdk.Query;
-
-namespace Celedon
-{
- ///
- /// Base class for all Plugins.
- ///
- /// Modified by Matt Barnes - "I've made a few special modifications myself"
- ///
- /// - Added the method RegisterEvent(), to simplify each child plugin constructor
- /// - Removed the base class constructor with the child class argument (it wasn't needed)
- /// - LocalPluginContext class now includes an OrganizationServiceContext object, so it doesn't need to be initialized within each plugin
- /// - LocalPluginContext class now implements IDisposable, so the OrganizationServiceContext object gets properly disposed when it is done
- /// - Added the Execution Stage constants
- /// - Added GetInputParameters() method for early binding of InputParameters
- /// - Added GetOutputParameters() method for early binding of OutputParameters
- /// - Added PreImage and PostImage - returns the first available image (assumes there is only one) if you have multiple, then retrieve them normally
- ///
- ///
- public class CeledonPlugin : IPlugin
- {
- public const int PREVALIDATION = 10;
- public const int PREOPERATION = 20;
- public const int POSTOPERATION = 40;
-
- public const string CREATEMESSAGE = "Create";
- public const string RETRIEVEMESSAGE = "Retrieve";
- public const string UPDATEMESSAGE = "Update";
- public const string DELETEMESSAGE = "Delete";
- public const string RETRIEVEMULTIPLEMESSAGE = "RetrieveMultiple";
- public const string ASSOCIATEMESSAGE = "Associate";
- public const string DISASSOCIATEMESSAGE = "Disassociate";
- public const string SETSTATEMESSAGE = "SetState";
-
- protected class LocalPluginContext : IDisposable
- {
- internal IServiceProvider ServiceProvider
- {
- get;
-
- private set;
- }
-
- internal IOrganizationService OrganizationService
- {
- get;
-
- private set;
- }
-
- internal OrganizationServiceContext OrganizationDataContext
- {
- get;
-
- private set;
- }
-
- internal IPluginExecutionContext PluginExecutionContext
- {
- get;
-
- private set;
- }
-
- internal ITracingService TracingService
- {
- get;
-
- private set;
- }
-
- private LocalPluginContext() { }
-
- internal LocalPluginContext(IServiceProvider serviceProvider)
- {
- if (serviceProvider == null)
- {
- throw new ArgumentNullException("serviceProvider");
- }
-
- // Obtain the execution context service from the service provider.
- this.PluginExecutionContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
-
- // Obtain the tracing service from the service provider.
- this.TracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
-
- // Obtain the Organization Service factory service from the service provider
- IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
-
- // Use the factory to generate the Organization Service.
- this.OrganizationService = factory.CreateOrganizationService(this.PluginExecutionContext.UserId);
-
- // Generate the Organization Data Context
- this.OrganizationDataContext = new OrganizationServiceContext(this.OrganizationService);
- }
-
- internal Entity PreImage
- {
- get { try { return this.PluginExecutionContext.PreEntityImages.Values.First(); } catch { throw new InvalidPluginExecutionException("Pre Image Not Found"); } }
- }
-
- internal Entity PostImage
- {
- get { try { return this.PluginExecutionContext.PostEntityImages.Values.First(); } catch { throw new InvalidPluginExecutionException("Post Image Not Found"); } }
- }
-
- internal T GetInputParameters() where T : class, ICrmRequest
- {
- switch (this.PluginExecutionContext.MessageName)
- {
- case CREATEMESSAGE:
- return new CreateInputParameters() { Target = this.PluginExecutionContext.InputParameters["Target"] as Entity } as T;
- case UPDATEMESSAGE:
- return new UpdateInputParameters() { Target = this.PluginExecutionContext.InputParameters["Target"] as Entity } as T;
- case DELETEMESSAGE:
- return new DeleteInputParameters() { Target = this.PluginExecutionContext.InputParameters["Target"] as EntityReference } as T;
- case RETRIEVEMESSAGE:
- return new RetrieveInputParameters() { Target = this.PluginExecutionContext.InputParameters["Target"] as EntityReference, ColumnSet = this.PluginExecutionContext.InputParameters["ColumnSet"] as ColumnSet, RelatedEntitiesQuery = this.PluginExecutionContext.InputParameters["RelatedEntitiesQuery"] as RelationshipQueryCollection } as T;
- case RETRIEVEMULTIPLEMESSAGE:
- return new RetrieveMultipleInputParameters() { Query = this.PluginExecutionContext.InputParameters["Query"] as QueryBase } as T;
- case ASSOCIATEMESSAGE:
- return new AssociateInputParameters() { Target = this.PluginExecutionContext.InputParameters["Target"] as EntityReference, Relationship = this.PluginExecutionContext.InputParameters["Relationship"] as Relationship, RelatedEntities = this.PluginExecutionContext.InputParameters["RelatedEntities"] as EntityReferenceCollection } as T;
- case DISASSOCIATEMESSAGE:
- return new DisassociateInputParameters() { Target = this.PluginExecutionContext.InputParameters["Target"] as EntityReference, Relationship = this.PluginExecutionContext.InputParameters["Relationship"] as Relationship, RelatedEntities = this.PluginExecutionContext.InputParameters["RelatedEntities"] as EntityReferenceCollection } as T;
- case SETSTATEMESSAGE:
- return new SetStateInputParameters() { EntityMoniker = this.PluginExecutionContext.InputParameters["EntityMoniker"] as EntityReference, State = this.PluginExecutionContext.InputParameters["State"] as OptionSetValue, Status = this.PluginExecutionContext.InputParameters["Status"] as OptionSetValue } as T;
- default:
- return default(T);
- }
- }
-
- internal T GetOutputParameters() where T : class, ICrmResponse
- {
- if (this.PluginExecutionContext.Stage < POSTOPERATION)
- {
- throw new InvalidOperationException("OutputParameters only exist during Post-Operation stage.");
- }
-
- switch (this.PluginExecutionContext.MessageName)
- {
- case CREATEMESSAGE:
- return new CreateOutputParameters() { Id = (Guid)this.PluginExecutionContext.OutputParameters["Id"] } as T;
- case RETRIEVEMESSAGE:
- return new RetrieveOutputParameters() { Entity = this.PluginExecutionContext.OutputParameters["Entity"] as Entity } as T;
- case RETRIEVEMULTIPLEMESSAGE:
- return new RetrieveMultipleOutputParameters() { EntityCollection = this.PluginExecutionContext.OutputParameters["BusinessEntityCollection"] as EntityCollection } as T;
- default:
- return default(T);
- }
- }
-
- internal void Trace(string message)
- {
- if (string.IsNullOrWhiteSpace(message) || this.TracingService == null)
- {
- return;
- }
-
- if (this.PluginExecutionContext == null)
- {
- this.TracingService.Trace(message);
- }
- else
- {
- this.TracingService.Trace("{0} : (Correlation Id: {1}, Initiating User: {2})", message, this.PluginExecutionContext.CorrelationId, this.PluginExecutionContext.InitiatingUserId);
- }
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (OrganizationDataContext != null)
- {
- OrganizationDataContext.Dispose();
- OrganizationDataContext = null;
- }
- }
- }
- }
-
- private Collection>> registeredEvents;
-
- ///
- /// Gets the List of events that the plug-in should fire for. Each List
- /// Item is a containing the Pipeline Stage, Message and (optionally) the Primary Entity.
- /// In addition, the fourth parameter provide the delegate to invoke on a matching registration.
- ///
- protected Collection>> RegisteredEvents
- {
- get
- {
- if (this.registeredEvents == null)
- {
- this.registeredEvents = new Collection>>();
- }
-
- return this.registeredEvents;
- }
- }
-
- protected void RegisterEvent(int Stage, string EventName, string EntityName, Action ExecuteMethod)
- {
- this.RegisteredEvents.Add(new Tuple>(Stage, EventName, EntityName, ExecuteMethod));
- }
-
- protected delegate void TraceDelegate(string message);
- protected TraceDelegate Trace;
-
- ///
- /// Gets or sets the name of the child class.
- ///
- /// The name of the child class.
- protected string ChildClassName
- {
- get { return this.GetType().Name; }
-
- //private set;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The of the derived class.
- //internal Plugin(Type childClassName)
- //{
- // this.ChildClassName = childClassName.ToString();
- //}
-
- ///
- /// Executes the plug-in.
- ///
- /// The service provider.
- ///
- /// 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.
- ///
- public void Execute(IServiceProvider serviceProvider)
- {
- if (serviceProvider == null)
- {
- throw new ArgumentNullException("serviceProvider");
- }
-
- // Construct the Local plug-in context.
- using (LocalPluginContext localcontext = new LocalPluginContext(serviceProvider))
- {
- localcontext.Trace(String.Format(CultureInfo.InvariantCulture, "Entered {0}.Execute()", this.ChildClassName));
-
- try
- {
- Trace = m => localcontext.Trace(m);
- // Iterate over all of the expected registered events to ensure that the plugin
- // has been invoked by an expected event
- // For any given plug-in event at an instance in time, we would expect at most 1 result to match.
- Action entityAction =
- (from a in this.RegisteredEvents
- where (
- a.Item1 == localcontext.PluginExecutionContext.Stage &&
- a.Item2 == localcontext.PluginExecutionContext.MessageName &&
- (String.IsNullOrWhiteSpace(a.Item3) ? true : a.Item3 == localcontext.PluginExecutionContext.PrimaryEntityName)
- )
- select a.Item4).FirstOrDefault();
-
- if (entityAction != null)
- {
- localcontext.Trace(String.Format(CultureInfo.InvariantCulture, "{0} is firing for Entity: {1}, Message: {2}", this.ChildClassName, localcontext.PluginExecutionContext.PrimaryEntityName, localcontext.PluginExecutionContext.MessageName));
-
- entityAction.Invoke(localcontext);
-
- // now exit - if the derived plug-in has incorrectly registered overlapping event registrations,
- // guard against multiple executions.
- return;
- }
- }
- catch (FaultException e)
- {
- localcontext.Trace(String.Format(CultureInfo.InvariantCulture, "Exception: {0}", e.ToString()));
-
- // Handle the exception.
- throw;
- }
- finally
- {
- localcontext.Trace(String.Format(CultureInfo.InvariantCulture, "Exiting {0}.Execute()", this.ChildClassName));
- }
- }
- }
-
- internal interface ICrmRequest { }
-
- internal class CreateInputParameters : ICrmRequest
- {
- internal Entity Target;
- }
-
- internal class UpdateInputParameters : ICrmRequest
- {
- internal Entity Target;
- }
-
- internal class DeleteInputParameters : ICrmRequest
- {
- internal EntityReference Target;
- }
-
- internal class RetrieveInputParameters : ICrmRequest
- {
- internal EntityReference Target;
- internal ColumnSet ColumnSet;
- internal RelationshipQueryCollection RelatedEntitiesQuery;
- }
-
- internal class RetrieveMultipleInputParameters : ICrmRequest
- {
- internal QueryBase Query;
- }
-
- internal class AssociateInputParameters : ICrmRequest
- {
- internal EntityReference Target;
- internal Relationship Relationship;
- internal EntityReferenceCollection RelatedEntities;
- }
-
- internal class DisassociateInputParameters : ICrmRequest
- {
- internal EntityReference Target;
- internal Relationship Relationship;
- internal EntityReferenceCollection RelatedEntities;
- }
-
- internal class SetStateInputParameters : ICrmRequest
- {
- internal EntityReference EntityMoniker;
- internal OptionSetValue State;
- internal OptionSetValue Status;
- }
-
- internal interface ICrmResponse { }
-
- internal class CreateOutputParameters : ICrmResponse
- {
- internal Guid Id;
- }
-
- internal class UpdateOutputParameters : ICrmResponse { }
-
- internal class DeleteOutputParameters : ICrmResponse { }
-
- internal class RetrieveOutputParameters : ICrmResponse
- {
- internal Entity Entity;
- }
-
- internal class RetrieveMultipleOutputParameters : ICrmResponse
- {
- internal EntityCollection EntityCollection;
- }
-
- internal class AssociateOutputParameters : ICrmResponse { }
-
- internal class DisassociateOutputParameters : ICrmResponse { }
-
- internal class SetStateOutputParameters : ICrmResponse { }
- }
-}
\ No newline at end of file
diff --git a/AutoNumber-Old/CreateAutoNumber.cs b/AutoNumber-Old/CreateAutoNumber.cs
deleted file mode 100644
index 84ac2fe..0000000
--- a/AutoNumber-Old/CreateAutoNumber.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-// Author: Matt Barnes (matt.barnes@celedonpartners.com)
-/*The MIT License (MIT)
-
-Copyright (c) 2015 Celedon Partners
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-// Generates a plugin step for an entity, when a new autonumber record is created
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using Microsoft.Xrm.Sdk;
-
-namespace Celedon
-{
- public class CreateAutoNumber : CeledonPlugin
- {
- //
- // This plugin is executed when a new AutoNumber record is created. It generates the plugin steps on the entity type to create each number
- //
- // Registration Details:
- // Message: Create
- // Primary Entity: cel_autonumber
- // User Context: SYSTEM
- // Event Pipeline: Post
- // Mode: Async
- // Config: none
- //
-
- internal const string PLUGIN_NAME = "CeledonPartners.AutoNumber.{0}";
-
- public CreateAutoNumber()
- {
- RegisterEvent(POSTOPERATION, CREATEMESSAGE, "cel_autonumber", Execute);
- }
-
- protected void Execute(LocalPluginContext Context)
- {
- Trace("Get Target record");
- Entity Target = Context.GetInputParameters().Target;
- string pluginName = String.Format(PLUGIN_NAME, Target.GetAttributeValue("cel_entityname"));
-
- if (Target.GetAttributeValue("cel_triggerevent").Value == 1)
- {
- pluginName += " Update";
- }
-
- Trace("Check for existing plugin step");
- if (Context.OrganizationDataContext.CreateQuery("sdkmessageprocessingstep").Where(s => s.GetAttributeValue("name").Equals(pluginName)).ToList().Any())
- {
- return; // Step already exists, nothing to do here.
- }
-
- Trace("Build the configuration");
- AutoNumberPluginConfig config = new AutoNumberPluginConfig()
- {
- EntityName = Target.GetAttributeValue("cel_entityname"),
- EventName = Target.GetAttributeValue("cel_triggerevent").Value == 1 ? "Update" : "Create"
- };
-
- Trace("Get the Id of this plugin");
- Guid PluginTypeId = Context.OrganizationDataContext.CreateQuery("plugintype")
- .Where(s => s.GetAttributeValue("name").Equals("Celedon.GetNextAutoNumber"))
- .Select(s => s.GetAttributeValue("plugintypeid"))
- .First();
-
- Trace("Get the message id from this org");
- Guid messageId = Context.OrganizationDataContext.CreateQuery("sdkmessage")
- .Where(s => s.GetAttributeValue("name").Equals(config.EventName))
- .Select(s => s.GetAttributeValue("sdkmessageid"))
- .First();
-
- Trace("Get the filterId for for the specific entity from this org");
- Guid filterId = Context.OrganizationDataContext.CreateQuery("sdkmessagefilter")
- .Where(s => s.GetAttributeValue("primaryobjecttypecode").Equals(config.EntityName)
- && s.GetAttributeValue("sdkmessageid").Id.Equals(messageId))
- .Select(s => s.GetAttributeValue("sdkmessagefilterid"))
- .First();
-
- Trace("Build new plugin step");
- Entity newPluginStep = new Entity("sdkmessageprocessingstep")
- {
- Attributes = new AttributeCollection()
- {
- { "name", pluginName },
- { "description", pluginName },
- { "plugintypeid", PluginTypeId.ToEntityReference("plugintype") }, // This plugin type
- { "sdkmessageid", messageId.ToEntityReference("sdkmessage") }, // Create or Update Message
- { "configuration", config.ToJSON() }, // EntityName and RegisteredEvent in the UnsecureConfig
- { "stage", PREOPERATION.ToOptionSetValue() }, // Execution Stage: Pre-Operation
- { "rank", 1 },
- { "impersonatinguserid", Context.PluginExecutionContext.UserId.ToEntityReference("systemuser") }, // Run as SYSTEM user. Assumes we are currently running as the SYSTEM user
- { "sdkmessagefilterid", filterId.ToEntityReference("sdkmessagefilter") },
- }
- };
-
- Trace("Create new plugin step");
- Guid pluginStepId = Context.OrganizationService.Create(newPluginStep);
- }
- }
-}
diff --git a/AutoNumber-Old/DeleteAutoNumber.cs b/AutoNumber-Old/DeleteAutoNumber.cs
deleted file mode 100644
index e0c5a7a..0000000
--- a/AutoNumber-Old/DeleteAutoNumber.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-// Author: Matt Barnes (matt.barnes@celedonpartners.com)
-/*The MIT License (MIT)
-
-Copyright (c) 2015 Celedon Partners
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-// Removes the plugin step from an entity, if there are no registered autonumber records
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-
-using Microsoft.Xrm.Sdk;
-
-namespace Celedon
-{
- public class DeleteAutoNumber : CeledonPlugin
- {
- //
- // This plugin is executed when an AutoNumber record is deleted, it will remove the plugin steps from the associated entity
- //
- // Registration details:
- // Message: Delete
- // Primary Entity: cel_autonumber
- // User Context: SYSTEM
- // Event Pipeline: Post
- // Mode: Async
- // Config: none
- //
- // PreImage:
- // Name: PreImage
- // Alias: PreImage
- // Attributes: cel_entityname, cel_attributename
- //
- public DeleteAutoNumber()
- {
- //this.RegisteredEvents.Add(new Tuple>(POSTOPERATION, DELETEMESSAGE, "entityname", new Action(Execute)));
- RegisterEvent(POSTOPERATION, DELETEMESSAGE, "cel_autonumber", Execute);
- }
-
- protected void Execute(LocalPluginContext Context)
- {
- int triggerEvent = Context.PreImage.Contains("cel_triggerevent") && Context.PreImage.GetAttributeValue("cel_triggerevent").Value == 1 ? 1 : 0;
-
- var remainingAutoNumberList = Context.OrganizationDataContext.CreateQuery("cel_autonumber")
- .Where(s => s.GetAttributeValue("cel_entityname").Equals(Context.PreImage.GetAttributeValue("cel_entityname")))
- .Select(s => new { Id = s.GetAttributeValue("cel_autonumberid"), TriggerEvent = s.Contains("cel_triggerevent") ? s.GetAttributeValue("cel_triggerevent").Value : 0 })
- .ToList();
-
- if (remainingAutoNumberList.Any(s => s.TriggerEvent == triggerEvent )) // If there are still other autonumber records on this entity, then do nothing.
- {
- return;
- }
-
- // Find and remove the registerd plugin
- string pluginName = String.Format(CreateAutoNumber.PLUGIN_NAME, Context.PreImage.GetAttributeValue("cel_entityname"));
- if (Context.PreImage.Contains("cel_triggerevent") && Context.PreImage.GetAttributeValue("cel_triggerevent").Value == 1)
- {
- pluginName += " Update";
- }
-
- var pluginStepList = Context.OrganizationDataContext.CreateQuery("sdkmessageprocessingstep")
- .Where(s => s.GetAttributeValue("name").Equals(pluginName))
- .Select(s => s.GetAttributeValue("sdkmessageprocessingstepid"))
- .ToList();
-
- if (!pluginStepList.Any()) // Plugin is already deleted, nothing to do here.
- {
- return;
- }
-
- // Delete plugin step
- Context.OrganizationService.Delete("sdkmessageprocessingstep", pluginStepList.First());
- }
- }
-}
diff --git a/AutoNumber-Old/GetNextAutoNumber.cs b/AutoNumber-Old/GetNextAutoNumber.cs
deleted file mode 100644
index 7705fb2..0000000
--- a/AutoNumber-Old/GetNextAutoNumber.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-// Author: Matt Barnes (matt.barnes@celedonpartners.com)
-/*The MIT License (MIT)
-
-Copyright (c) 2015 Celedon Partners
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-// Gets the next available number and adds it to the Target
-
-using System;
-using System.Linq;
-using Microsoft.Xrm.Sdk;
-using Microsoft.Xrm.Sdk.Query;
-
-namespace Celedon
-{
- public class getNextAutoNumber : CeledonPlugin
- {
- //
- // This is the main plugin that creates the numbers and adds them to new records
- // This plugin is not registered by default. It is registered and unregistered dynamically by the CreateAutoNumber and DeleteAutoNumber plugins respectively
- //
-
- private AutoNumberPluginConfig config;
-
- public getNextAutoNumber(string pluginConfig, string secureConfig)
- {
- // Need to support older version
- if (pluginConfig.TryParseJSON(out config))
- {
- RegisterEvent(PREOPERATION, config.EventName, config.EntityName, Execute);
- }
- else
- {
- RegisterEvent(PREOPERATION, CREATEMESSAGE, pluginConfig, Execute);
- }
-
-
- }
-
- protected void Execute(LocalPluginContext context)
- {
- #region Get the list of autonumber records applicable to the Target entity type
- int triggerEvent = context.PluginExecutionContext.MessageName == "Update" ? 1 : 0;
- var autoNumberIdList = context.OrganizationDataContext.CreateQuery("cel_autonumber")
- .Where(a => a.GetAttributeValue("cel_entityname").Equals(context.PluginExecutionContext.PrimaryEntityName) && a.GetAttributeValue("statecode").Value == 0 && a.GetAttributeValue("cel_triggerevent").Value == triggerEvent)
- .OrderBy(a => a.GetAttributeValue("cel_autonumberid")) // Insure they are ordered, to prevent deadlocks
- .Select(a => a.GetAttributeValue("cel_autonumberid"));
- #endregion
-
- #region This loop locks the autonumber record(s) so only THIS transaction can read/write it
- foreach (Guid autoNumberId in autoNumberIdList)
- {
- Entity lockingUpdate = new Entity("cel_autonumber");
- lockingUpdate.Id = autoNumberId;
- lockingUpdate["cel_preview"] = "555"; // Use the preview field as our "dummy" field - so we don't need a dedicated "dummy"
-
- context.OrganizationService.Update(lockingUpdate);
- }
- #endregion
-
- #region This loop populates the Target record, and updates the autonumber record(s)
- Entity Target = context.PluginExecutionContext.InputParameters["Target"] as Entity;
-
- foreach (Guid autoNumberId in autoNumberIdList)
- {
- Entity autoNumber = context.OrganizationService.Retrieve("cel_autonumber", autoNumberId, true);
- string targetAttribute = autoNumber.GetAttributeValue("cel_attributename");
-
- #region Check conditions that prevent creating an autonumber
- if (context.PluginExecutionContext.MessageName == "Update" && !Target.Contains(autoNumber.GetAttributeValue("cel_triggerattribute")))
- {
- continue; // Continue, if this is an Update event and the Target does not contain the trigger value
- }
- else if ((autoNumber.Contains("cel_conditionaloptionset") && (!Target.Contains(autoNumber.GetAttributeValue("cel_conditionaloptionset")) || Target.GetAttributeValue(autoNumber.GetAttributeValue("cel_conditionaloptionset")).Value != autoNumber.GetAttributeValue("cel_conditionalvalue"))))
- {
- continue; // Continue, if this is a conditional optionset
- }
- else if (Target.Contains(targetAttribute) && !String.IsNullOrWhiteSpace(Target.GetAttributeValue(targetAttribute)))
- {
- continue; // Continue, so we don't overwrite an existing value
- }
- #endregion
-
- #region Create the AutoNumber
- int numDigits = autoNumber.GetAttributeValue("cel_digits");
-
- // Generate number and insert into Target Record
- Target[targetAttribute] = String.Format("{0}{1}{2}", ReplaceParameters(autoNumber.GetAttributeValue("cel_prefix"), Target, context.OrganizationService),
- numDigits == 0 ? "" : autoNumber.GetAttributeValue("cel_nextnumber").ToString("D" + numDigits),
- ReplaceParameters(autoNumber.GetAttributeValue("cel_suffix"), Target, context.OrganizationService));
-
- // Increment next number in db
- Entity updatedAutoNumber = new Entity("cel_autonumber");
- updatedAutoNumber.Id = autoNumber.Id;
- updatedAutoNumber["cel_nextnumber"] = autoNumber.GetAttributeValue("cel_nextnumber") + 1;
- updatedAutoNumber["cel_preview"] = Target[targetAttribute]; // fix the preview
-
- context.OrganizationService.Update(updatedAutoNumber);
- #endregion
- }
- #endregion
- }
-
- #region Process Runtime Parameters, if any
- private string ReplaceParameters(string text, Entity Target, IOrganizationService Service)
- {
- if (String.IsNullOrWhiteSpace(text))
- {
- return "";
- }
-
- foreach (RuntimeParameter param in RuntimeParameter.GetParametersFromString(text))
- {
- if (!param.IsParentParameter())
- {
- text = text.Replace(param.ParameterText, param.GetParameterValue(Target));
- }
- else
- {
- if (Target.Contains(param.ParentLookupName))
- {
- var parentRecord = Service.Retrieve(Target.GetAttributeValue(param.ParentLookupName).LogicalName, Target.GetAttributeValue(param.ParentLookupName).Id, new ColumnSet(param.AttributeName));
- text = text.Replace(param.ParameterText, param.GetParameterValue(parentRecord));
- }
- else // Target record has no parent, so use default value
- {
- text = text.Replace(param.ParameterText, param.DefaultValue);
- }
- }
- }
-
- return text;
- }
- #endregion
- }
-}
diff --git a/AutoNumber-Old/Properties/AssemblyInfo.cs b/AutoNumber-Old/Properties/AssemblyInfo.cs
deleted file mode 100644
index c58809e..0000000
--- a/AutoNumber-Old/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("AutoNumber")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("AutoNumber")]
-[assembly: AssemblyCopyright("Copyright © 2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: CLSCompliant(true)]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("4dc971d5-7361-46ff-9df8-f6571ce6fc4c")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoNumber-Old/RuntimeParameter.cs b/AutoNumber-Old/RuntimeParameter.cs
deleted file mode 100644
index df313ec..0000000
--- a/AutoNumber-Old/RuntimeParameter.cs
+++ /dev/null
@@ -1,436 +0,0 @@
-// Author: Matt Barnes (matt.barnes@celedonpartners.com)
-/*The MIT License (MIT)
-
-Copyright (c) 2015 Celedon Partners
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-// Class for storing and processing Runtime Parameters in the Autonumber configuration
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-using Microsoft.Xrm.Sdk;
-
-namespace Celedon
-{
- public class RuntimeParameter
- {
- public string ParameterText { get; private set; }
- public string AttributeName { get; private set; }
- public string ParentLookupName { get; private set; }
- public string DefaultValue { get; private set; }
- public string StringFormatter { get; private set; }
- public ConditionalFormatter Conditional { get; private set; }
-
- private RuntimeParameter() : this("", "", "", "", "", new ConditionalFormatter()) { }
- public RuntimeParameter(string paramText, string attributeText, string parentLookup, string defaultValue, string stringFormat, ConditionalFormatter condition)
- {
- ParameterText = paramText;
- AttributeName = attributeText;
- ParentLookupName = parentLookup;
- DefaultValue = defaultValue;
- StringFormatter = stringFormat;
- Conditional = condition;
- }
-
- public static RuntimeParameter Parse(string input)
- {
- RuntimeParameter rp = new RuntimeParameter();
- rp.ParameterText = input;
- rp.AttributeName = input.Trim('{', '}');
-
- if (rp.AttributeName.Contains(':'))
- {
- string[] paramList = rp.AttributeName.Split(':');
- rp.AttributeName = paramList[0];
-
- if (rp.AttributeName == "rand")
- {
- rp.StringFormatter = paramList[1];
- }
- else
- {
- if (paramList[1].Contains('?'))
- {
- rp.Conditional = ConditionalFormatter.Parse(paramList[1]);
- }
- else if (paramList.Length > 2)
- {
- rp.StringFormatter = paramList[1];
- rp.Conditional = ConditionalFormatter.Parse(paramList[2]);
- }
- else
- {
- rp.StringFormatter = paramList[1];
- }
- }
- }
-
- if (rp.AttributeName.Contains('|'))
- {
- rp.DefaultValue = rp.AttributeName.Split('|')[1];
- rp.AttributeName = rp.AttributeName.Split('|')[0];
- }
-
- if (rp.AttributeName.Contains('.'))
- {
- rp.ParentLookupName = rp.AttributeName.Split('.')[0];
- rp.AttributeName = rp.AttributeName.Split('.')[1];
- }
-
- return rp;
- }
-
- public static IEnumerable GetParametersFromString(string text)
- {
- foreach (string p in Regex.Matches(text, @"{(.*?)}").OfType().Select(m => m.Groups[0].Value).Distinct())
- {
- yield return Parse(p);
- }
- }
-
- public string GetParameterValue(Entity Target)
- {
- if (Target.Contains(AttributeName))
- {
- if (Target[AttributeName] is EntityReference)
- {
- // Lookup condition is based on GUID
- return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue(AttributeName).Id) : Target.GetAttributeValue(AttributeName).Name;
- }
- else if (Target[AttributeName] is OptionSetValue)
- {
- // Conditional OptionSetValue is based on the integer value
- return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue(AttributeName).Value.ToString()) : Target.FormattedValues[AttributeName];
- }
- else if (Target[AttributeName] is bool)
- {
- // Note: Boolean values ignore the match value, they just use the attribute value itself as the condition
- return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue(AttributeName)) : Target.FormattedValues[AttributeName];
- }
- else if (Target[AttributeName] is DateTime)
- {
- // If there is a format AND a condition, apply formatting first, then evaluate condition as a string
- // If there is a condition without any format, evaluate condition as DateTime
- return String.IsNullOrEmpty(StringFormatter) ? Conditional.GetResult(Target.GetAttributeValue(AttributeName)) : Conditional.GetResult(Target.GetAttributeValue(AttributeName).ToString(StringFormatter));
- }
- else if (Target[AttributeName] is Money)
- {
- return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue(AttributeName).Value) : Target.GetAttributeValue(AttributeName).Value.ToString(StringFormatter);
- }
- else if (Target[AttributeName] is int)
- {
- return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue(AttributeName)) : Target.GetAttributeValue(AttributeName).ToString(StringFormatter);
- }
- else if (Target[AttributeName] is decimal)
- {
- return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue(AttributeName)) : Target.GetAttributeValue(AttributeName).ToString(StringFormatter);
- }
- else if (Target[AttributeName] is double)
- {
- return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue(AttributeName)) : Target.GetAttributeValue(AttributeName).ToString(StringFormatter);
- }
- else if (Target[AttributeName] is string)
- {
- return Conditional.GetResult(Target[AttributeName].ToString());
- }
- }
- else if (AttributeName.Equals("rand"))
- {
- string length = "";
- string stringStyle = "upper";
- int stringLength = 5; // Seems like reasonable default
-
- if (StringFormatter.Contains('?'))
- {
- length = StringFormatter.Split('?')[0];
- stringStyle = StringFormatter.Split('?')[1].ToLower();
- }
- else
- {
- length = StringFormatter;
- }
-
- if (!Int32.TryParse(length, out stringLength))
- {
- stringLength = 5;
- }
-
- string stringValues = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (stringStyle == "mix")
- {
- stringValues = stringValues + stringValues.ToLower();
- }
- else if (stringStyle == "lower")
- {
- stringValues = stringValues.ToLower();
- }
-
- Random rnd = new Random();
- return String.Join("", Enumerable.Range(0, stringLength).Select(n => stringValues[rnd.Next(stringValues.Length)]));
- }
-
- return DefaultValue;
- }
-
- public bool IsParentParameter()
- {
- return !String.IsNullOrEmpty(ParentLookupName);
- }
-
- public bool IsRandomParameter()
- {
- return AttributeName.Equals("rand");
- }
-
- public class ConditionalFormatter
- {
- private char Operator;
- private ConditionalFormatter FalseCondition = null;
- public string MatchValue { get; private set; }
- public string TrueValue { get; private set; }
- public string FalseValue { get; private set; }
-
- public ConditionalFormatter() : this("", "", "") { }
- public ConditionalFormatter(string matchValue, string trueValue, string falseValue)
- {
- Operator = matchValue.StartsWith(">") || matchValue.StartsWith("<") ? matchValue[0] : '=';
- MatchValue = matchValue.TrimStart('>', '<');
- TrueValue = trueValue;
- FalseValue = falseValue;
-
- if (falseValue.Contains('?')) // if any nested conditions
- {
- string[] condition1 = falseValue.Split(new char[] { '?' }, 2);
- string[] condition2 = condition1[1].Split(new char[] { '|' }, 2);
- FalseCondition = new ConditionalFormatter(condition1[0], condition2[0], condition2[1]);
- }
- }
-
- public static ConditionalFormatter Parse(string conditionalString)
- {
- string[] condition1 = conditionalString.Split(new char[] { '?' }, 2);
- string[] condition2 = condition1[1].Split(new char[] { '|' }, 2);
-
- return new ConditionalFormatter(condition1[0], condition2[0], condition2[1]);
- }
-
- public bool HasCondition
- {
- get { return !String.IsNullOrEmpty(MatchValue); }
- }
-
- public bool IsRecursive
- {
- get { return FalseCondition != null; }
- }
-
- public string GetResult(string inputText)
- {
- if (!this.HasCondition)
- {
- return inputText;
- }
-
- if (this.IsRecursive)
- {
- return inputText == MatchValue ? TrueValue : FalseCondition.GetResult(inputText);
- }
- else
- {
- return inputText == MatchValue ? TrueValue : FalseValue;
- }
- }
-
- public string GetResult(Guid inputGuid)
- {
- if (!this.HasCondition)
- {
- return inputGuid.ToString();
- }
-
- if (this.IsRecursive)
- {
- return CompareGuid(inputGuid) ? TrueValue : FalseCondition.GetResult(inputGuid);
- }
- else
- {
- return CompareGuid(inputGuid) ? TrueValue : FalseValue;
- }
- }
-
- public string GetResult(int inputInt)
- {
- if (!this.HasCondition)
- {
- return inputInt.ToString();
- }
-
- if (this.IsRecursive)
- {
- return CompareNumeric(inputInt) ? TrueValue : FalseCondition.GetResult(inputInt);
- }
- else
- {
- return CompareNumeric(inputInt) ? TrueValue : FalseValue;
- }
- }
-
- public string GetResult(double inputDouble)
- {
- if (!this.HasCondition)
- {
- return inputDouble.ToString();
- }
-
- if (this.IsRecursive)
- {
- return CompareNumeric((decimal)inputDouble) ? TrueValue : FalseCondition.GetResult(inputDouble);
- }
- else
- {
- return CompareNumeric((decimal)inputDouble) ? TrueValue : FalseValue;
- }
- }
-
- public string GetResult(decimal inputDecimal)
- {
- if (!this.HasCondition)
- {
- return inputDecimal.ToString();
- }
-
- if (this.IsRecursive)
- {
- return CompareNumeric((decimal)inputDecimal) ? TrueValue : FalseCondition.GetResult(inputDecimal);
- }
- else
- {
- return CompareNumeric((decimal)inputDecimal) ? TrueValue : FalseValue;
- }
- }
-
- public string GetResult(DateTime inputDate)
- {
- if (!this.HasCondition)
- {
- return inputDate.ToString();
- }
-
- if (this.IsRecursive)
- {
- return CompareDateTime(inputDate) ? TrueValue : FalseCondition.GetResult(inputDate);
- }
- else
- {
- return CompareDateTime(inputDate) ? TrueValue : FalseValue;
- }
- }
-
- private bool CompareGuid(Guid id)
- {
- Guid matchGuid;
- if (Guid.TryParse(MatchValue, out matchGuid))
- {
- return id.Equals(matchGuid);
- }
- else
- {
- return id.ToString().Equals(MatchValue);
- }
- }
-
- private bool CompareDateTime(DateTime date)
- {
- DateTime matchDate;
- if (DateTime.TryParse(MatchValue, out matchDate))
- {
- switch (Operator)
- {
- case '>':
- return date > matchDate;
- case '<':
- return date < matchDate;
- default:
- return date == matchDate;
- }
- }
- else
- {
- return date.ToShortDateString() == MatchValue;
- }
- }
-
- private bool CompareNumeric(decimal number)
- {
- decimal matchNumber;
- if (Decimal.TryParse(MatchValue, out matchNumber))
- {
- switch (Operator)
- {
- case '>':
- return number > matchNumber;
- case '<':
- return number < matchNumber;
- default:
- return number == matchNumber;
- }
- }
- else
- {
- return number.ToString() == MatchValue;
- }
- }
-
- public string GetResult(bool value)
- {
- // Boolean only has 2 possible values, so it doesn't support recursive conditions
- return value ? TrueValue : FalseValue;
- }
-
- public override bool Equals(Object obj)
- {
- return obj is ConditionalFormatter && this == (ConditionalFormatter)obj;
- }
- public override int GetHashCode()
- {
- return MatchValue.GetHashCode() ^ TrueValue.GetHashCode() ^ FalseValue.GetHashCode();
- }
- public static bool operator ==(ConditionalFormatter x, ConditionalFormatter y)
- {
- if (Object.ReferenceEquals(null, x) && Object.ReferenceEquals(null, y))
- {
- return true;
- }
- else if (Object.ReferenceEquals(null, x) || Object.ReferenceEquals(null, y))
- {
- return false;
- }
- return x.MatchValue == y.MatchValue && x.TrueValue == y.TrueValue && x.FalseValue == y.FalseValue && x.FalseCondition == y.FalseCondition;
- }
- public static bool operator !=(ConditionalFormatter x, ConditionalFormatter y)
- {
- return !(x == y);
- }
- }
- }
-}
diff --git a/AutoNumber-Old/ValidateAutoNumber.cs b/AutoNumber-Old/ValidateAutoNumber.cs
deleted file mode 100644
index 07939e3..0000000
--- a/AutoNumber-Old/ValidateAutoNumber.cs
+++ /dev/null
@@ -1,243 +0,0 @@
-// Author: Matt Barnes (matt.barnes@celedonpartners.com)
-/*The MIT License (MIT)
-
-Copyright (c) 2015 Celedon Partners
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-// Validation on pre-create of a new AutoNumber record
-
-#define VALIDATEPARAMETERS // temporarily disable this, until it can be made to work
-#define DUPLICATECHECK
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-
-using Microsoft.Xrm.Sdk;
-using Microsoft.Xrm.Sdk.Messages;
-using Microsoft.Xrm.Sdk.Metadata;
-using System.Text.RegularExpressions;
-
-namespace Celedon
-{
- public class ValidateAutoNumber : CeledonPlugin
- {
- //
- // This Plugin will validate the details of a new AutoNumber record before it is created
- //
- // Registration Details:
- // Message: Create
- // Primary Entity: cel_autonumber
- // User Context: SYSTEM
- // Event Pipeline: PreValidation
- // Mode: Sync
- // Config: none
- //
- private LocalPluginContext Context;
- private Dictionary> EntityMetadata;
- private Dictionary AttributeMetadata;
-
- public ValidateAutoNumber(string unsecureConfig, string secureConfig)
- {
- EntityMetadata = new Dictionary>();
- AttributeMetadata = new Dictionary();
-
- RegisterEvent(PREVALIDATION, CREATEMESSAGE, "cel_autonumber", Execute);
- }
-
- protected void Execute(LocalPluginContext context)
- {
- Context = context;
-
- Trace("Getting Target entity");
- Entity Target = Context.GetInputParameters().Target;
- Trace("Validate the Entity name");
- Trace("Get Attribute List");
- List attributeList = GetEntityMetadata(Target.GetAttributeValue("cel_entityname"));
-
- Trace("Validate the Attribute name");
- if (!attributeList.Select(a => a.LogicalName).Contains(Target.GetAttributeValue("cel_attributename")))
- {
- throw new InvalidPluginExecutionException("Specified Attribute does not exist.");
- }
-
- Trace("Validate the Trigger Attribute (if any)");
- if (!String.IsNullOrEmpty(Target.GetAttributeValue("cel_triggerattribute")) && !attributeList.Select(a => a.LogicalName).Contains(Target.GetAttributeValue("cel_triggerattribute")))
- {
- throw new InvalidPluginExecutionException("Specified Trigger Attribute does not exist.");
- }
-
- Trace("Validate the Attribute type");
- if (attributeList.Single(a => a.LogicalName.Equals(Target.GetAttributeValue("cel_attributename"))).AttributeType != AttributeTypeCode.String && attributeList.Single(a => a.LogicalName.Equals(Target.GetAttributeValue("cel_attributename"))).AttributeType != AttributeTypeCode.Memo)
- {
- throw new InvalidPluginExecutionException("Attribute must be a text field.");
- }
-
- #region test parameters
-#if VALIDATEPARAMETERS
- Dictionary fields = new Dictionary() { { "cel_prefix", "Prefix" }, { "cel_suffix", "Suffix" } };
-
- foreach (string field in fields.Keys)
- {
- if (Target.Contains(field) && Target.GetAttributeValue(field).Contains('{'))
- {
- if (Target.GetAttributeValue(field).Count(c => c.Equals('{')) != Target.GetAttributeValue(field).Count(c => c.Equals('}')))
- {
- throw new InvalidPluginExecutionException(String.Format("Invalid parameter formatting in {0}", fields[field]));
- }
-
- foreach (string p in Regex.Matches(Target.GetAttributeValue(field), @"{(.*?)}").OfType().Select(m => m.Groups[0].Value).Distinct())
- {
- if (p.Substring(1).Contains('{'))
- {
- throw new InvalidPluginExecutionException(String.Format("Invalid parameter formatting in {0}", fields[field]));
- }
- }
-
- try
- {
- foreach (RuntimeParameter param in RuntimeParameter.GetParametersFromString(Target.GetAttributeValue(field)))
- {
- if (!param.IsParentParameter())
- {
- if (!attributeList.Select(a => a.LogicalName).Contains(param.AttributeName))
- {
- throw new InvalidPluginExecutionException(String.Format("{0} is not a valid attribute name in {1} value", param.AttributeName, fields[field]));
- }
- }
- else
- {
- if (!attributeList.Select(a => a.LogicalName).Contains(param.ParentLookupName))
- {
- throw new InvalidPluginExecutionException(String.Format("{0} is not a valid attribute name in {1} value", param.ParentLookupName, fields[field]));
- }
-
- if (attributeList.Single(a => a.LogicalName.Equals(param.ParentLookupName)).AttributeType != AttributeTypeCode.Lookup && attributeList.Single(a => a.LogicalName.Equals(param.ParentLookupName)).AttributeType != AttributeTypeCode.Customer && attributeList.Single(a => a.LogicalName.Equals(param.ParentLookupName)).AttributeType != AttributeTypeCode.Owner)
- {
- throw new InvalidPluginExecutionException(String.Format("{0} must be a Lookup attribute type in {1} value", param.ParentLookupName, fields[field]));
- }
-
- var parentLookupAttribute = (LookupAttributeMetadata)GetAttributeMetadata(Target.GetAttributeValue("cel_entityname"), param.ParentLookupName);
- if (!parentLookupAttribute.Targets.Any(e => GetEntityMetadata(e).Select(a => a.LogicalName).Contains(param.AttributeName)))
- {
- throw new InvalidPluginExecutionException(String.Format("invalid attribute on {0} parent entity, in {1} value", param.ParentLookupName, fields[field]));
- }
-
- }
- }
- }
- catch (InvalidPluginExecutionException)
- {
- throw;
- }
- catch
- {
- throw new InvalidPluginExecutionException(String.Format("Failed to parse Runtime Parameters in {0} value.", fields[field]));
- }
- }
- }
-#endif
- #endregion
-
- if (Target.Contains("cel_conditionaloptionset"))
- {
- Trace("Validate Conditional OptionSet");
- if (!attributeList.Select(a => a.LogicalName).Contains(Target.GetAttributeValue("cel_conditionaloptionset")))
- {
- throw new InvalidPluginExecutionException("Specified Conditional OptionSet does not exist");
- }
-
- if (attributeList.Single(a => a.LogicalName.Equals(Target.GetAttributeValue("cel_conditionaloptionset"))).AttributeType != AttributeTypeCode.Picklist)
- {
- throw new InvalidPluginExecutionException("Conditional Attribute must be an OptionSet");
- }
-
- Trace("Validate Conditional Value");
- PicklistAttributeMetadata optionSetMetadata = (PicklistAttributeMetadata)GetAttributeMetadata(Target.GetAttributeValue("cel_entityname"), Target.GetAttributeValue("cel_conditionaloptionset"));//attributeResponse.AttributeMetadata;
- if (!optionSetMetadata.OptionSet.Options.Select(o => o.Value).Contains(Target.GetAttributeValue("cel_conditionalvalue")))
- {
- throw new InvalidPluginExecutionException("Conditional Value does not exist in OptionSet");
- }
- }
-
- #region Duplicate Check
-#if DUPLICATECHECK
- Trace("Validate there are no duplicates");
- // TODO: Fix this. duplicate detection works when all fields contain data, but fails when some fields are empty
- var autoNumberList = Context.OrganizationDataContext.CreateQuery("cel_autonumber")
- .Where(a => a.GetAttributeValue("cel_entityname").Equals(Target.GetAttributeValue("cel_entityname")) && a.GetAttributeValue("cel_attributename").Equals(Target.GetAttributeValue("cel_attributename")))
- .Select(a => new { Id = a.GetAttributeValue("cel_autonumberid"), ConditionalOption = a.GetAttributeValue("cel_conditionaloptionset"), ConditionalValue = a.GetAttributeValue("cel_conditionalvalue") })
- .ToList();
-
-
- if (!Target.Contains("cel_conditionaloptionset") && autoNumberList.Any())
- {
- throw new InvalidPluginExecutionException("Duplicate AutoNumber record exists.");
- }
- else if (autoNumberList.Where(a => a.ConditionalOption.Equals(Target.GetAttributeValue("cel_conditionaloptionset")) && a.ConditionalValue.Equals(Target.GetAttributeValue("cel_conditionalvalue"))).Any())
- {
- throw new InvalidPluginExecutionException("Duplicate AutoNumber record exists.");
- }
-#endif
- #endregion
-
- Trace("Insert the autoNumber Name attribute");
- Target["cel_name"] = String.Format("AutoNumber for {0}, {1}", Target.GetAttributeValue("cel_entityname"), Target.GetAttributeValue("cel_attributename"));
- }
-
- private AttributeMetadata GetAttributeMetadata(string entityName, string attributeName)
- {
- string attributeKey = entityName + attributeName;
- if (!AttributeMetadata.ContainsKey(attributeKey))
- {
- try
- {
- RetrieveAttributeResponse attributeResponse = (RetrieveAttributeResponse)Context.OrganizationService.Execute(new RetrieveAttributeRequest() { EntityLogicalName = entityName, LogicalName = attributeName });
- AttributeMetadata.Add(attributeKey, attributeResponse.AttributeMetadata);
- }
- catch
- {
- throw new InvalidPluginExecutionException(String.Format("{1} attribute does not exist on {0} entity, or entity does not exist.", entityName, attributeName));
- }
- }
-
- return AttributeMetadata[attributeKey];
- }
-
- private List GetEntityMetadata(string entityName)
- {
- if (!EntityMetadata.ContainsKey(entityName))
- {
- try
- {
- RetrieveEntityResponse response = (RetrieveEntityResponse)Context.OrganizationDataContext.Execute(new RetrieveEntityRequest() { EntityFilters = EntityFilters.Attributes, LogicalName = entityName });
- EntityMetadata.Add(entityName, response.EntityMetadata.Attributes.ToList()); // Keep the list of Attributes
- }
- catch
- {
- throw new InvalidPluginExecutionException(String.Format("{0} Entity does not exist.", entityName));
- }
- }
-
- return EntityMetadata[entityName].ToList();
- }
- }
-}
diff --git a/AutoNumber.Tests/App.config b/AutoNumber.Tests/App.config
index a8ebc20..e8b889d 100644
--- a/AutoNumber.Tests/App.config
+++ b/AutoNumber.Tests/App.config
@@ -1,8 +1,8 @@
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
+
diff --git a/AutoNumber.Tests/AutoNumber.Tests.csproj b/AutoNumber.Tests/AutoNumber.Tests.csproj
index 25c1bd7..23777b8 100644
--- a/AutoNumber.Tests/AutoNumber.Tests.csproj
+++ b/AutoNumber.Tests/AutoNumber.Tests.csproj
@@ -8,7 +8,7 @@
Properties
AutoNumber.Tests
AutoNumber.Tests
- v4.5
+ v4.0
512
{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10.0
@@ -38,84 +38,38 @@
false
-
- ..\packages\Microsoft.CrmSdk.Extensions.6.0.4\lib\net40\AntiXSSLibrary.dll
- True
-
-
- ..\packages\Castle.Core.4.1.0\lib\net45\Castle.Core.dll
- True
+
+ ..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll
- ..\packages\Microsoft.CrmSdk.CoreAssemblies.6.1.2\lib\net45\Microsoft.Crm.Sdk.Proxy.dll
- True
+ ..\packages\Microsoft.CrmSdk.CoreAssemblies.6.0.0\lib\net40\Microsoft.Crm.Sdk.Proxy.dll
..\packages\Microsoft.IdentityModel.6.1.7600.16394\lib\net35\Microsoft.IdentityModel.dll
True
-
- ..\packages\WindowsAzure.ServiceBus.2.1.2.0\lib\net40-full\Microsoft.ServiceBus.dll
- True
-
-
- ..\packages\Microsoft.WindowsAzure.ConfigurationManager.2.0.0.0\lib\net40\Microsoft.WindowsAzure.Configuration.dll
- True
-
-
- ..\packages\Microsoft.CrmSdk.Extensions.6.0.4\lib\net40\Microsoft.Xrm.Client.dll
- True
-
-
- ..\packages\Microsoft.CrmSdk.Extensions.6.0.4\lib\net40\Microsoft.Xrm.Client.CodeGeneration.dll
- True
-
-
- ..\packages\Microsoft.CrmSdk.Extensions.6.0.4\lib\net40\Microsoft.Xrm.Portal.dll
- True
-
-
- ..\packages\Microsoft.CrmSdk.Extensions.6.0.4\lib\net40\Microsoft.Xrm.Portal.Files.dll
- True
-
- ..\packages\Microsoft.CrmSdk.CoreAssemblies.6.1.2\lib\net45\Microsoft.Xrm.Sdk.dll
- True
+ ..\packages\Microsoft.CrmSdk.CoreAssemblies.6.0.0\lib\net40\Microsoft.Xrm.Sdk.dll
-
- ..\packages\Microsoft.CrmSdk.Deployment.6.1.1\lib\net45\Microsoft.Xrm.Sdk.Deployment.dll
- True
+
+ ..\packages\Moq.4.7.142\lib\net45\Moq.dll
-
- ..\packages\Moq.4.7.63\lib\net45\Moq.dll
- True
+
+ ..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -123,11 +77,7 @@
-
-
-
-
-
+
@@ -141,6 +91,8 @@
+
+
SettingsSingleFileGenerator
@@ -153,6 +105,31 @@
AutoNumber
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoNumber.Tests/Properties/AssemblyInfo.cs b/AutoNumber.Tests/Properties/AssemblyInfo.cs
index 78ec067..4d1b783 100644
--- a/AutoNumber.Tests/Properties/AssemblyInfo.cs
+++ b/AutoNumber.Tests/Properties/AssemblyInfo.cs
@@ -10,7 +10,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AutoNumber.Tests")]
-[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyCopyright("Copyright © Celedon Partners 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
diff --git a/AutoNumber.Tests/Properties/Settings.Designer.cs b/AutoNumber.Tests/Properties/Settings.Designer.cs
index deb5f81..210ea7d 100644
--- a/AutoNumber.Tests/Properties/Settings.Designer.cs
+++ b/AutoNumber.Tests/Properties/Settings.Designer.cs
@@ -12,7 +12,7 @@ namespace AutoNumber.Tests.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
diff --git a/AutoNumber.Tests/UnitTests.cs b/AutoNumber.Tests/UnitTests.cs
index 5093d74..01a3b25 100644
--- a/AutoNumber.Tests/UnitTests.cs
+++ b/AutoNumber.Tests/UnitTests.cs
@@ -1,13 +1,13 @@
using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xrm.Sdk;
+using NUnit.Framework;
namespace Celedon
{
- [TestClass]
+ [TestFixture]
public class AutoNumberUnitTest
{
- [TestMethod]
+ [Test]
public void RuntimeParameterParseTest1()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName}");
@@ -22,7 +22,7 @@ public void RuntimeParameterParseTest1()
Assert.AreEqual(rp.StringFormatter, String.Empty);
}
- [TestMethod]
+ [Test]
public void RuntimeParameterParseTest2()
{
RuntimeParameter rp = RuntimeParameter.Parse("{parentLookup.parentAttribute}");
@@ -36,7 +36,8 @@ public void RuntimeParameterParseTest2()
Assert.AreEqual(rp.DefaultValue, String.Empty);
Assert.AreEqual(rp.StringFormatter, String.Empty);
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest3()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName|defaultValue}");
@@ -50,7 +51,8 @@ public void RuntimeParameterParseTest3()
Assert.AreEqual(rp.ParentLookupName, String.Empty);
Assert.AreEqual(rp.StringFormatter, String.Empty);
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest4()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:formatString}");
@@ -64,7 +66,8 @@ public void RuntimeParameterParseTest4()
Assert.AreEqual(rp.DefaultValue, String.Empty);
Assert.AreEqual(rp.ParentLookupName, String.Empty);
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest5()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:matchValue?trueValue|falseValue}");
@@ -82,7 +85,8 @@ public void RuntimeParameterParseTest5()
Assert.AreEqual(rp.Conditional.GetResult("matchValue"), "trueValue");
Assert.AreEqual(rp.Conditional.GetResult("other"), "falseValue");
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest6()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:match1?result1|match2?result2|match3?result3|elseResult}");
@@ -101,7 +105,8 @@ public void RuntimeParameterParseTest6()
Assert.AreEqual(rp.Conditional.GetResult("match3"), "result3");
Assert.AreEqual(rp.Conditional.GetResult("other"), "elseResult");
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest7()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:formatString:matchValue?trueValue|falseValue}");
@@ -119,7 +124,8 @@ public void RuntimeParameterParseTest7()
Assert.AreEqual(rp.Conditional.GetResult("other"), "falseValue");
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest8()
{
RuntimeParameter rp = RuntimeParameter.Parse("{parentLookup.parentAttribute:formatString:matchValue?trueValue|falseValue}");
@@ -136,7 +142,8 @@ public void RuntimeParameterParseTest8()
Assert.AreEqual(rp.Conditional.GetResult("matchValue"), "trueValue");
Assert.AreEqual(rp.Conditional.GetResult("other"), "falseValue");
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest9()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName|defaultValue:formatString:matchValue?trueValue|falseValue}");
@@ -153,7 +160,8 @@ public void RuntimeParameterParseTest9()
Assert.AreEqual(rp.Conditional.GetResult("matchValue"), "trueValue");
Assert.AreEqual(rp.Conditional.GetResult("other"), "falseValue");
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest10()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:>100?trueValue|falseValue}");
@@ -170,7 +178,8 @@ public void RuntimeParameterParseTest10()
Assert.AreEqual(rp.Conditional.GetResult(101), "trueValue");
Assert.AreEqual(rp.Conditional.GetResult(99), "falseValue");
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest11()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:<2015-1-1?trueValue|falseValue}");
@@ -187,7 +196,8 @@ public void RuntimeParameterParseTest11()
Assert.AreEqual(rp.Conditional.GetResult(new DateTime(2014,1,1)), "trueValue");
Assert.AreEqual(rp.Conditional.GetResult(new DateTime(2016,1,1)), "falseValue");
}
- [TestMethod]
+
+ [Test]
public void RuntimeParameterParseTest12()
{
RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:yyyy:2015?trueValue|falseValue}");
@@ -199,7 +209,7 @@ public void RuntimeParameterParseTest12()
// Stuff that should not be populated
Assert.AreEqual(rp.DefaultValue, String.Empty);
Assert.AreEqual(rp.ParentLookupName, String.Empty);
-
+
// Conditional test cases
Entity test = new Entity();
test["attributeName"] = new DateTime(2015,1,1);
diff --git a/AutoNumber.Tests/packages.config b/AutoNumber.Tests/packages.config
index de38e99..118a10b 100644
--- a/AutoNumber.Tests/packages.config
+++ b/AutoNumber.Tests/packages.config
@@ -1,11 +1,8 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/AutoNumber.WebResources/Properties/AssemblyInfo.cs b/AutoNumber.WebResources/Properties/AssemblyInfo.cs
index 1bb5990..242ba77 100644
--- a/AutoNumber.WebResources/Properties/AssemblyInfo.cs
+++ b/AutoNumber.WebResources/Properties/AssemblyInfo.cs
@@ -10,7 +10,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AutoNumber.WebResources")]
-[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyCopyright("Copyright © Celedon Partners 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
diff --git a/AutoNumber.sln b/AutoNumber.sln
index 75f9773..c72b16a 100644
--- a/AutoNumber.sln
+++ b/AutoNumber.sln
@@ -1,12 +1,14 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26430.16
+VisualStudioVersion = 15.0.27004.2002
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoNumber", "AutoNumber\AutoNumber.csproj", "{56E63E6D-35E9-48B5-A549-1321610F197A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoNumber.WebResources", "AutoNumber.WebResources\AutoNumber.WebResources.csproj", "{68670149-40FE-4EA9-A624-572B2C595F69}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoNumber.Tests", "AutoNumber.Tests\AutoNumber.Tests.csproj", "{CBE6269C-2B9B-460C-9AE1-89DA739B30A8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -21,8 +23,15 @@ Global
{68670149-40FE-4EA9-A624-572B2C595F69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68670149-40FE-4EA9-A624-572B2C595F69}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68670149-40FE-4EA9-A624-572B2C595F69}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CBE6269C-2B9B-460C-9AE1-89DA739B30A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CBE6269C-2B9B-460C-9AE1-89DA739B30A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CBE6269C-2B9B-460C-9AE1-89DA739B30A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CBE6269C-2B9B-460C-9AE1-89DA739B30A8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {0FC25342-9536-4C7B-996B-F5A0EDFDBF99}
+ EndGlobalSection
EndGlobal
diff --git a/AutoNumber/AutoNumber.csproj b/AutoNumber/AutoNumber.csproj
index 5b91633..f404a66 100644
--- a/AutoNumber/AutoNumber.csproj
+++ b/AutoNumber/AutoNumber.csproj
@@ -9,7 +9,7 @@
Properties
Celedon
Celedon.AutoNumber
- v4.5
+ v4.0
512
@@ -40,19 +40,17 @@
- ..\packages\Microsoft.CrmSdk.CoreAssemblies.6.1.2\lib\net45\Microsoft.Crm.Sdk.Proxy.dll
- True
+ ..\packages\Microsoft.CrmSdk.CoreAssemblies.6.0.0\lib\net40\Microsoft.Crm.Sdk.Proxy.dll
..\packages\Microsoft.IdentityModel.6.1.7600.16394\lib\net35\Microsoft.IdentityModel.dll
True
- ..\packages\Microsoft.CrmSdk.CoreAssemblies.6.1.2\lib\net45\Microsoft.Xrm.Sdk.dll
- True
+ ..\packages\Microsoft.CrmSdk.CoreAssemblies.6.0.0\lib\net40\Microsoft.Xrm.Sdk.dll
-
+
@@ -61,11 +59,8 @@
-
-
-
-
+
@@ -88,15 +83,37 @@
-
- Designer
-
+
SettingsSingleFileGenerator
Settings.Designer.cs
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/AutoNumberUnitTest/UnitTests.cs b/AutoNumberUnitTest/UnitTests.cs
deleted file mode 100644
index 5093d74..0000000
--- a/AutoNumberUnitTest/UnitTests.cs
+++ /dev/null
@@ -1,211 +0,0 @@
-using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Microsoft.Xrm.Sdk;
-
-namespace Celedon
-{
- [TestClass]
- public class AutoNumberUnitTest
- {
- [TestMethod]
- public void RuntimeParameterParseTest1()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.Conditional, new RuntimeParameter.ConditionalFormatter());
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
- Assert.AreEqual(rp.StringFormatter, String.Empty);
- }
-
- [TestMethod]
- public void RuntimeParameterParseTest2()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{parentLookup.parentAttribute}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "parentAttribute");
- Assert.AreEqual(rp.ParentLookupName, "parentLookup");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.Conditional, new RuntimeParameter.ConditionalFormatter());
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.StringFormatter, String.Empty);
- }
- [TestMethod]
- public void RuntimeParameterParseTest3()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName|defaultValue}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
- Assert.AreEqual(rp.DefaultValue, "defaultValue");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.Conditional, new RuntimeParameter.ConditionalFormatter());
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
- Assert.AreEqual(rp.StringFormatter, String.Empty);
- }
- [TestMethod]
- public void RuntimeParameterParseTest4()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:formatString}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
- Assert.AreEqual(rp.StringFormatter, "formatString");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.Conditional, new RuntimeParameter.ConditionalFormatter());
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
- }
- [TestMethod]
- public void RuntimeParameterParseTest5()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:matchValue?trueValue|falseValue}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
- Assert.AreEqual(rp.Conditional.MatchValue, "matchValue");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
- Assert.AreEqual(rp.StringFormatter, String.Empty);
-
- // Conditional test cases
- Assert.AreEqual(rp.Conditional.GetResult("matchValue"), "trueValue");
- Assert.AreEqual(rp.Conditional.GetResult("other"), "falseValue");
- }
- [TestMethod]
- public void RuntimeParameterParseTest6()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:match1?result1|match2?result2|match3?result3|elseResult}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
- Assert.AreEqual(rp.StringFormatter, String.Empty);
-
- // Conditional test cases
- Assert.AreEqual(rp.Conditional.GetResult("match1"), "result1");
- Assert.AreEqual(rp.Conditional.GetResult("match2"), "result2");
- Assert.AreEqual(rp.Conditional.GetResult("match3"), "result3");
- Assert.AreEqual(rp.Conditional.GetResult("other"), "elseResult");
- }
- [TestMethod]
- public void RuntimeParameterParseTest7()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:formatString:matchValue?trueValue|falseValue}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
- Assert.AreEqual(rp.StringFormatter, "formatString");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
-
- // Conditional test cases
- Assert.AreEqual(rp.Conditional.GetResult("matchValue"), "trueValue");
- Assert.AreEqual(rp.Conditional.GetResult("other"), "falseValue");
-
- }
- [TestMethod]
- public void RuntimeParameterParseTest8()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{parentLookup.parentAttribute:formatString:matchValue?trueValue|falseValue}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "parentAttribute");
- Assert.AreEqual(rp.ParentLookupName, "parentLookup");
- Assert.AreEqual(rp.StringFormatter, "formatString");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.DefaultValue, String.Empty);
-
- // Conditional test cases
- Assert.AreEqual(rp.Conditional.GetResult("matchValue"), "trueValue");
- Assert.AreEqual(rp.Conditional.GetResult("other"), "falseValue");
- }
- [TestMethod]
- public void RuntimeParameterParseTest9()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName|defaultValue:formatString:matchValue?trueValue|falseValue}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
- Assert.AreEqual(rp.DefaultValue, "defaultValue");
- Assert.AreEqual(rp.StringFormatter, "formatString");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
-
- // Conditional test cases
- Assert.AreEqual(rp.Conditional.GetResult("matchValue"), "trueValue");
- Assert.AreEqual(rp.Conditional.GetResult("other"), "falseValue");
- }
- [TestMethod]
- public void RuntimeParameterParseTest10()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:>100?trueValue|falseValue}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
- Assert.AreEqual(rp.StringFormatter, String.Empty);
-
- // Conditional test cases
- Assert.AreEqual(rp.Conditional.GetResult(101), "trueValue");
- Assert.AreEqual(rp.Conditional.GetResult(99), "falseValue");
- }
- [TestMethod]
- public void RuntimeParameterParseTest11()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:<2015-1-1?trueValue|falseValue}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
- Assert.AreEqual(rp.StringFormatter, String.Empty);
-
- // Conditional test cases
- Assert.AreEqual(rp.Conditional.GetResult(new DateTime(2014,1,1)), "trueValue");
- Assert.AreEqual(rp.Conditional.GetResult(new DateTime(2016,1,1)), "falseValue");
- }
- [TestMethod]
- public void RuntimeParameterParseTest12()
- {
- RuntimeParameter rp = RuntimeParameter.Parse("{attributeName:yyyy:2015?trueValue|falseValue}");
-
- // Stuff that should be populated
- Assert.AreEqual(rp.AttributeName, "attributeName");
- Assert.AreEqual(rp.StringFormatter, "yyyy");
-
- // Stuff that should not be populated
- Assert.AreEqual(rp.DefaultValue, String.Empty);
- Assert.AreEqual(rp.ParentLookupName, String.Empty);
-
- // Conditional test cases
- Entity test = new Entity();
- test["attributeName"] = new DateTime(2015,1,1);
- Assert.AreEqual(rp.GetParameterValue(test), "trueValue");
- test["attributeName"] = new DateTime(2016, 1, 1);
- Assert.AreEqual(rp.GetParameterValue(test), "falseValue");
- }
- }
-}
diff --git a/README.md b/README.md
index 0638807..64dc2e8 100644
--- a/README.md
+++ b/README.md
@@ -15,13 +15,16 @@ The following is required to build AutoNumber:
* [Microsoft Visual Studio 2015 or 2017](https://www.visualstudio.com/vs/older-downloads/)
* [CRM Developer Toolkit - by Jason Lattimer](https://github.com/jlattimer/CRMDeveloperExtensions)
-The current version builds against the Dynamics CRM 2016 - v8.2.0.2 SDK
+> The current version builds against the Dynamics CRM 2016 - v6.0 SDK and .Net 4.0. You can [look here](https://blogs.msdn.microsoft.com/crm/2017/02/01/dynamics-365-sdk-backwards-compatibility/) for more information on SDK compatibilities. Since this solution does not connect to CRM Via alternative methods we do not need to update the connectivity support that changed in the later versions of CRM-Online for OAuth support.
## v1.2
+> The plugin distributed with this version is *NOT* compatible with previous versions. You can import this Solution over the existing as an upgrade but you will need to convert the existing auto-number steps to the new plug-in in order to maintain support.
+
* Updated Code Formatting - *ReSharper* all the things!
* Refactored code to be *Thread Safe*
-* Updated solution to v8.2
-* Updated SDK to v8.2.0.2
+* Packaged Solution is exported for v8.0 (2016 RTM) - this means support for the v1.2 Solution is supported in 8.x + (Including 9.0) versions of CRM.
+* SDK Version is set to 6.0.0
+* Added back the test cases and converted to NUnit so that travis-ci can build
## v1.1:
* Supports custom prefix and suffix
diff --git a/Solutions/CeledonAutoNumber_1_2_0_0.zip b/Solutions/CeledonAutoNumber_1_2_0_0.zip
new file mode 100644
index 0000000..2821931
Binary files /dev/null and b/Solutions/CeledonAutoNumber_1_2_0_0.zip differ
diff --git a/Solutions/CeledonAutoNumber_1_2_0_0_managed.zip b/Solutions/CeledonAutoNumber_1_2_0_0_managed.zip
new file mode 100644
index 0000000..ada44b5
Binary files /dev/null and b/Solutions/CeledonAutoNumber_1_2_0_0_managed.zip differ
diff --git a/Solutions/WARNING.MD b/Solutions/WARNING.MD
new file mode 100644
index 0000000..51e06ba
--- /dev/null
+++ b/Solutions/WARNING.MD
@@ -0,0 +1 @@
+If you import the un-managed solution this will overwrite the site-map. This solution was intended for development purposes only! Backup your site-map if you intend to release it with your own internal solutions and restore after importing.